home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / xshogi11.lha / xshogi-1.1 / xshogi.c < prev    next >
C/C++ Source or Header  |  1993-04-28  |  144KB  |  5,296 lines

  1.  
  2. #define XBOARD_VERSION "2.0"
  3.  
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <signal.h>
  7. #include <sys/ioctl.h>
  8. #include <time.h>
  9. #ifdef HAS_GETTIMEOFDAY
  10. #ifndef ESIX
  11. #include <sys/time.h>
  12. #endif
  13. #endif
  14. #ifdef    __STDC__
  15. #ifndef ESIX
  16. #ifndef apollo
  17. #include <stdlib.h>
  18. #endif 
  19. #endif
  20. #endif
  21. #if    SYSTEM_FIVE || SYSV
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #ifdef    AIXV3
  25. #include <fcntl.h>
  26. #else
  27. #include <sys/fcntl.h>
  28. #endif AIXV3
  29. #if    SVR4
  30. #include <stropts.h>
  31. #endif
  32. #endif
  33. #if defined(__STDC__) || SYSTEM_FIVE || SYSV
  34. #include <string.h>
  35. #else
  36. #include <strings.h>
  37. #endif
  38. #include <pwd.h>
  39.  
  40. #ifdef IRIS
  41. #include <sys/sysmacros.h>
  42. #endif
  43.  
  44. #include <X11/Intrinsic.h>
  45. #include <X11/StringDefs.h>
  46. #include <X11/Shell.h>
  47. #include <X11/Xaw/Dialog.h>
  48. #include <X11/Xaw/Form.h>
  49. #include <X11/Xaw/List.h>
  50. #include <X11/Xaw/Label.h>
  51. #include <X11/Xaw/SimpleMenu.h>
  52. #include <X11/Xaw/SmeBSB.h>
  53. #include <X11/Xaw/SmeLine.h>
  54. #include <X11/cursorfont.h>
  55.  
  56. #include "version.h"
  57. #include "xshogi.h"
  58.  
  59.  
  60. #include "eastern_bitmaps/icon.xbm"
  61.  
  62. #include "eastern_bitmaps/bigsolid.xbm"
  63. #include "eastern_bitmaps/smallsolid.xbm"
  64. #include "eastern_bitmaps/bigsolidR.xbm"
  65. #include "eastern_bitmaps/smallsolidR.xbm"
  66.  
  67. #ifdef WESTERN_BITMAPS
  68.  
  69. #include "western_bitmaps/none.xbm"
  70.  
  71. #include "western_bitmaps/king.xbm"
  72. #include "western_bitmaps/rook.xbm"
  73. #include "western_bitmaps/rookP.xbm"
  74. #include "western_bitmaps/bishop.xbm"
  75. #include "western_bitmaps/bishopP.xbm"
  76. #include "western_bitmaps/gold.xbm"
  77. #include "western_bitmaps/silver.xbm"
  78. #include "western_bitmaps/silverP.xbm"
  79. #include "western_bitmaps/knight.xbm"
  80. #include "western_bitmaps/knightP.xbm"
  81. #include "western_bitmaps/lance.xbm"
  82. #include "western_bitmaps/lanceP.xbm"
  83. #include "western_bitmaps/pawn.xbm"
  84. #include "western_bitmaps/pawnP.xbm"
  85.  
  86. #include "western_bitmaps/kingR.xbm"
  87. #include "western_bitmaps/rookR.xbm"
  88. #include "western_bitmaps/rookPR.xbm"
  89. #include "western_bitmaps/bishopR.xbm"
  90. #include "western_bitmaps/bishopPR.xbm"
  91. #include "western_bitmaps/goldR.xbm"
  92. #include "western_bitmaps/silverR.xbm"
  93. #include "western_bitmaps/silverPR.xbm"
  94. #include "western_bitmaps/knightR.xbm"
  95. #include "western_bitmaps/knightPR.xbm"
  96. #include "western_bitmaps/lanceR.xbm"
  97. #include "western_bitmaps/lancePR.xbm"
  98. #include "western_bitmaps/pawnR.xbm"
  99. #include "western_bitmaps/pawnPR.xbm"
  100.  
  101. #else
  102.  
  103. #include "eastern_bitmaps/none.xbm"
  104.  
  105. #include "eastern_bitmaps/king.xbm"
  106. #include "eastern_bitmaps/rook.xbm"
  107. #include "eastern_bitmaps/rookP.xbm"
  108. #include "eastern_bitmaps/bishop.xbm"
  109. #include "eastern_bitmaps/bishopP.xbm"
  110. #include "eastern_bitmaps/gold.xbm"
  111. #include "eastern_bitmaps/silver.xbm"
  112. #include "eastern_bitmaps/silverP.xbm"
  113. #include "eastern_bitmaps/knight.xbm"
  114. #include "eastern_bitmaps/knightP.xbm"
  115. #include "eastern_bitmaps/lance.xbm"
  116. #include "eastern_bitmaps/lanceP.xbm"
  117. #include "eastern_bitmaps/pawn.xbm"
  118. #include "eastern_bitmaps/pawnP.xbm"
  119.  
  120. #include "eastern_bitmaps/kingR.xbm"
  121. #include "eastern_bitmaps/rookR.xbm"
  122. #include "eastern_bitmaps/rookPR.xbm"
  123. #include "eastern_bitmaps/bishopR.xbm"
  124. #include "eastern_bitmaps/bishopPR.xbm"
  125. #include "eastern_bitmaps/goldR.xbm"
  126. #include "eastern_bitmaps/silverR.xbm"
  127. #include "eastern_bitmaps/silverPR.xbm"
  128. #include "eastern_bitmaps/knightR.xbm"
  129. #include "eastern_bitmaps/knightPR.xbm"
  130. #include "eastern_bitmaps/lanceR.xbm"
  131. #include "eastern_bitmaps/lancePR.xbm"
  132. #include "eastern_bitmaps/pawnR.xbm"
  133. #include "eastern_bitmaps/pawnPR.xbm"
  134.  
  135. #include "eastern_bitmaps/none_m.xbm"
  136.  
  137. #include "eastern_bitmaps/bigsolid_m.xbm"
  138. #include "eastern_bitmaps/smallsolid_m.xbm"
  139. #include "eastern_bitmaps/bigsolidR_m.xbm"
  140. #include "eastern_bitmaps/smallsolidR_m.xbm"
  141.  
  142. #include "eastern_bitmaps/king_m.xbm"
  143. #include "eastern_bitmaps/rook_m.xbm"
  144. #include "eastern_bitmaps/rookP_m.xbm"
  145. #include "eastern_bitmaps/bishop_m.xbm"
  146. #include "eastern_bitmaps/bishopP_m.xbm"
  147. #include "eastern_bitmaps/gold_m.xbm"
  148. #include "eastern_bitmaps/silver_m.xbm"
  149. #include "eastern_bitmaps/silverP_m.xbm"
  150. #include "eastern_bitmaps/knight_m.xbm"
  151. #include "eastern_bitmaps/knightP_m.xbm"
  152. #include "eastern_bitmaps/lance_m.xbm"
  153. #include "eastern_bitmaps/lanceP_m.xbm"
  154. #include "eastern_bitmaps/pawn_m.xbm"
  155. #include "eastern_bitmaps/pawnP_m.xbm"
  156.  
  157. #include "eastern_bitmaps/kingR_m.xbm"
  158. #include "eastern_bitmaps/rookR_m.xbm"
  159. #include "eastern_bitmaps/rookPR_m.xbm"
  160. #include "eastern_bitmaps/bishopR_m.xbm"
  161. #include "eastern_bitmaps/bishopPR_m.xbm"
  162. #include "eastern_bitmaps/goldR_m.xbm"
  163. #include "eastern_bitmaps/silverR_m.xbm"
  164. #include "eastern_bitmaps/silverPR_m.xbm"
  165. #include "eastern_bitmaps/knightR_m.xbm"
  166. #include "eastern_bitmaps/knightPR_m.xbm"
  167. #include "eastern_bitmaps/lanceR_m.xbm"
  168. #include "eastern_bitmaps/lancePR_m.xbm"
  169. #include "eastern_bitmaps/pawnR_m.xbm"
  170. #include "eastern_bitmaps/pawnPR_m.xbm"
  171.  
  172. #include "eastern_bitmaps/none_l.xbm"
  173.  
  174. #include "eastern_bitmaps/bigsolid_l.xbm"
  175. #include "eastern_bitmaps/smallsolid_l.xbm"
  176. #include "eastern_bitmaps/bigsolidR_l.xbm"
  177. #include "eastern_bitmaps/smallsolidR_l.xbm"
  178.  
  179. #include "eastern_bitmaps/king_l.xbm"
  180. #include "eastern_bitmaps/rook_l.xbm"
  181. #include "eastern_bitmaps/rookP_l.xbm"
  182. #include "eastern_bitmaps/bishop_l.xbm"
  183. #include "eastern_bitmaps/bishopP_l.xbm"
  184. #include "eastern_bitmaps/gold_l.xbm"
  185. #include "eastern_bitmaps/silver_l.xbm"
  186. #include "eastern_bitmaps/silverP_l.xbm"
  187. #include "eastern_bitmaps/knight_l.xbm"
  188. #include "eastern_bitmaps/knightP_l.xbm"
  189. #include "eastern_bitmaps/lance_l.xbm"
  190. #include "eastern_bitmaps/lanceP_l.xbm"
  191. #include "eastern_bitmaps/pawn_l.xbm"
  192. #include "eastern_bitmaps/pawnP_l.xbm"
  193.  
  194. #include "eastern_bitmaps/kingR_l.xbm"
  195. #include "eastern_bitmaps/rookR_l.xbm"
  196. #include "eastern_bitmaps/rookPR_l.xbm"
  197. #include "eastern_bitmaps/bishopR_l.xbm"
  198. #include "eastern_bitmaps/bishopPR_l.xbm"
  199. #include "eastern_bitmaps/goldR_l.xbm"
  200. #include "eastern_bitmaps/silverR_l.xbm"
  201. #include "eastern_bitmaps/silverPR_l.xbm"
  202. #include "eastern_bitmaps/knightR_l.xbm"
  203. #include "eastern_bitmaps/knightPR_l.xbm"
  204. #include "eastern_bitmaps/lanceR_l.xbm"
  205. #include "eastern_bitmaps/lancePR_l.xbm"
  206. #include "eastern_bitmaps/pawnR_l.xbm"
  207. #include "eastern_bitmaps/pawnPR_l.xbm"
  208.  
  209. #endif
  210.  
  211. void main P((int argc, char **argv));
  212. void CreateGCs P((void));
  213. void CreatePieces P((void));
  214. void CreatePieceMenus P((void));
  215. void PieceMenuPopup P((Widget w, XEvent *event, String *params,
  216.             Cardinal *num_params));
  217. static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
  218. static void SetBlackToPlay P((void));
  219. static void SetWhiteToPlay P((void));
  220. void ReadBitmap P((String name, Pixmap *pm, Pixmap *qm,
  221.     char small_bits[], char medium_bits[], char large_bits[]));
  222. void CreateGrid P((void));
  223. int EventToSquare P((int x));
  224. int EventToXSquare P((int x));
  225. ChessSquare CharToPiece P((int c, int p));
  226. void DrawSquare P((int row, int column, ChessSquare piece));
  227. void BlinkSquare P((int row, int column, ChessSquare piece));
  228. void EventProc P((Widget widget, caddr_t unused, XEvent *event));
  229. void DrawPosition P((Widget w, XExposeEvent *event));
  230. void InitPosition P((void));
  231. void CopyBoard P((Board to, Board from));
  232. void CopyCatches P((Catched to, Catched from));
  233. void ClearCatches P((Catched to));
  234. void UpdateCatched P((int c, int f, int d, int a, int cm));
  235. void SendCurrentBoard P((FILE *fp));
  236. void SendBoard P((FILE *fp, Board board, Catched catches));
  237. void HandleUserMove P((Widget w, XEvent *event));
  238. void FinishUserMove P((ChessMove move_type, int to_x, int to_y));
  239. void HandleMachineMove P((char *message, FILE *fp));
  240. void ReadGameFile P((void));
  241. int ReadGameFileProc P((void));
  242. void MakeMove P((ChessMove *move_type, int from_x, int from_y,
  243.     int to_x, int to_y));
  244. void InitChessProgram P((char *host_name, char *program_name, int *pid,
  245.     FILE **to, FILE **from, XtIntervalId *xid));
  246. void ShutdownChessPrograms P((char *message));
  247. void CommentPopUp P((char *label));
  248. void FileNamePopUp P((char *label, void (*proc)(char *name)));
  249. void FileNameCallback P((Widget w, XtPointer client_data,
  250.              XtPointer call_data));
  251. void FileNameAction P((Widget w, XEvent *event));
  252. void PromotionPopUp P((ChessSquare piece, int to_x, int to_y));
  253. void PromotionCallback P((Widget w, XtPointer client_data,
  254.               XtPointer call_data));
  255. void FileModePopUp P((char *name));
  256. void FileModeCallback P((Widget w, XtPointer client_data,
  257.               XtPointer call_data));
  258. void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
  259. void ModeHighlight P((void));
  260. void GameProc P((void));
  261. void QuitProc P((void));
  262. int PlayFromGameFileProc P((char *name));
  263. void MachinePlaysWhiteProc P((void));
  264. void ForwardProc P((void));
  265. void ResetFileProc P((void));
  266. void ResetProc P((void));
  267. int SetupPositionFromFileProc P((char *name));
  268. void MachinePlaysBlackProc P((void));
  269. void BackwardProc P((void));
  270. void FlipProc P((void));
  271. void SaveGameProc P((char *name));
  272. void SwitchProc P((void));
  273. void EditPositionProc P((void));
  274. void EditPositionDone P((void));
  275. void ForceProc P((void));
  276. void HintProc P((void));
  277. void SavePositionProc P((char *name));
  278. void TwoMachinesPlayProc P((void));
  279. void PauseProc P((void));
  280. void Iconify P((void));
  281. void SendToProgram P((char *message, FILE *fp));
  282. void ReceiveFromProgram P((FILE *fp, int *source, XtInputId *id));
  283. void SendSearchDepth P((FILE *fp));
  284. void DisplayMessage P((char *message));
  285. void DisplayName P((char *name));
  286. void Attention P((int pid));
  287. void DisplayClocks P((int clock_mode));
  288. void DisplayTimerLabel P((Widget w, char *color, long timer));
  289. char *TimeString P((long tm));
  290. void Usage P((void));
  291. char *StrStr P((char *string, char *match));
  292. int StrCaseCmp P((char *s1, char *s2));
  293. int ToLower P((int c));
  294. int ToUpper P((int c));
  295. #if    SYSTEM_FIVE || SYSV
  296. char *PseudoTTY P((int *ptyv));
  297. #else
  298. void CatchPipeSignal P((int dummy));
  299. #endif
  300. #define off_board(x) (x < 2 || x > BOARD_SIZE+1)
  301. extern void parseGameFile P((void));
  302.  
  303. /*
  304.  * XShogi depends on Xt R4 or higher
  305.  */
  306. int xtVersion = XtSpecificationRelease;
  307.  
  308. int xScreen;
  309. Display *xDisplay;
  310. Window xBoardWindow;
  311. GC lightSquareGC, darkSquareGC, lineGC, wdPieceGC, wlPieceGC,
  312.     bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
  313.     charPieceGC, dropPiece;
  314. Pixmap reversePawnBitmap, reverseLanceBitmap, reverseKnightBitmap, reverseSilverBitmap,
  315.        reverseGoldBitmap, reverseBishopBitmap, reverseRookBitmap,
  316.        reversePPawnBitmap, reversePLanceBitmap, reversePKnightBitmap,
  317.        reversePSilverBitmap, reversePBishopBitmap, reversePRookBitmap, 
  318.        reverseKingBitmap, 
  319.        reverseBigSolidBitmap, reverseSmallSolidBitmap,
  320.        normalBigSolidBitmap, normalSmallSolidBitmap,
  321.        normalPawnBitmap, normalLanceBitmap, normalKnightBitmap, 
  322.        normalSilverBitmap, normalGoldBitmap, 
  323.        normalBishopBitmap, normalRookBitmap,
  324.        normalPPawnBitmap, normalPLanceBitmap, normalPKnightBitmap,
  325.        normalPSilverBitmap, normalPBishopBitmap, normalPRookBitmap,
  326.        normalKingBitmap, iconPixmap;  
  327. Widget shellWidget, formWidget, boardWidget, commandsWidget, messageWidget,
  328.     blackTimerWidget, whiteTimerWidget, nameWidget, widgetList[6], 
  329.         commentShell, promotionShell, blackPieceMenu, whitePieceMenu,
  330.     filemodeShell;
  331. XSegment gridSegments[(BOARD_SIZE + 1) * 2];
  332. XtIntervalId firstProgramXID = 0, secondProgramXID = 0,
  333.     readGameXID = 0, timerXID = 0, blinkSquareXID = 0;
  334. XFontStruct *labelFont, *coordFont;
  335. XtAppContext appContext;
  336. void (*fileProc) P((char *name));
  337.  
  338. FILE *fromFirstProgFP, *toFirstProgFP, *fromSecondProgFP,
  339.     *toSecondProgFP, *gameFileFP, *lastMsgFP;
  340. int currentMove = 0, forwardMostMove = 0, firstProgramPID = 0,
  341.     secondProgramPID = 0, squareSize = SMALL_SQUARE_SIZE, fromX = -1,
  342.     fromY = -1, firstMove = True, flipView = False,
  343.     xshogiDebug = True, commentUp = False, filenameUp = False,
  344.         whitePlaysFirst = False, startedFromSetupPosition = False,
  345.     promotionUp = False, searchTime = 0, pmFromX = -1, pmFromY = -1,
  346.         blackFlag = False, whiteFlag = False, maybeThinking = False,
  347.     filemodeUp = False;
  348. Pixel timerForegroundPixel, timerBackgroundPixel;
  349. MatchMode matchMode = MatchFalse;
  350. GameMode gameMode = BeginningOfGame, lastGameMode = BeginningOfGame;
  351. BoardSize boardSize = Small;
  352. char moveList[MAX_MOVES][MOVE_LEN], parseList[MAX_MOVES][MOVE_LEN * 2],
  353.     ptyname[24], *chessDir, *programName;
  354.  
  355. long blackTimeRemaining, whiteTimeRemaining, timeControl;
  356. extern char currentMoveString[];
  357.  
  358. int black_pixel_is_zero;
  359.                      
  360. Catched catches[MAX_MOVES];
  361.  
  362.  
  363. #define pawn 0
  364. #define lance 1
  365. #define knight 2
  366. #define silver 3
  367. #define gold 4
  368. #define bishop 5
  369. #define rook 6
  370. #define king 7
  371. #define no_piece 8
  372.                        
  373.  
  374. char catchedIndexToChar[8] = {
  375.   'P', 'L', 'N', 'S', 'G', 'B', 'R', 'K'
  376. };
  377.  
  378. ChessSquare catchedIndexToPiece[2][8] = {
  379.    BlackPawn, BlackLance, BlackKnight, BlackSilver, BlackGold,
  380.    BlackBishop, BlackRook, BlackKing,
  381.    WhitePawn, WhiteLance, WhiteKnight, WhiteSilver, WhiteGold,
  382.    WhiteBishop, WhiteRook, WhiteKing
  383. };
  384.  
  385.  
  386. pieceToCatchedIndex[] = {
  387.    pawn, lance, knight, silver, gold, bishop, rook,
  388.    pawn, lance, knight, silver, bishop, rook, king,
  389.    pawn, lance, knight, silver, gold, bishop, rook,
  390.    pawn, lance, knight, silver, bishop, rook, king,
  391.    no_piece
  392. };
  393.  
  394.  
  395.  
  396. Board boards[MAX_MOVES], initialPosition = {
  397.     { BlackLance, BlackKnight, BlackSilver, BlackGold, BlackKing,
  398.               BlackGold, BlackSilver, BlackKnight, BlackLance },
  399.         { EmptySquare, BlackBishop, EmptySquare, EmptySquare, EmptySquare,
  400.               EmptySquare, EmptySquare, BlackRook, EmptySquare }, 
  401.         { BlackPawn, BlackPawn, BlackPawn, BlackPawn, BlackPawn, 
  402.               BlackPawn, BlackPawn, BlackPawn, BlackPawn },
  403.     { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare, 
  404.         EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,  
  405.     { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare, 
  406.         EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,  
  407.     { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare, 
  408.         EmptySquare, EmptySquare, EmptySquare, EmptySquare } ,  
  409.         { WhitePawn, WhitePawn, WhitePawn, WhitePawn, WhitePawn, 
  410.         WhitePawn, WhitePawn, WhitePawn, WhitePawn },
  411.         { EmptySquare, WhiteRook, EmptySquare, EmptySquare, EmptySquare,
  412.               EmptySquare, EmptySquare, WhiteBishop, EmptySquare }, 
  413.     { WhiteLance, WhiteKnight, WhiteSilver, WhiteGold, WhiteKing,
  414.               WhiteGold, WhiteSilver, WhiteKnight, WhiteLance }
  415. };
  416.  
  417. String buttonStrings[] = {
  418.     "Quit", "Load Game", "Machine White", "Forward",
  419.     "Reset", "Load Position", "Machine Black", "Backward",
  420.     "Flip View", "Save Game", "Force Moves", "Pause",
  421.     "Hint", "Save Position", "Two Machines", "Edit Position"
  422. };
  423. /* must be in same order as buttonStrings! */
  424. typedef enum {
  425.     ButtonQuit, ButtonLoadGame, ButtonMachineWhite, ButtonForward,
  426.     ButtonReset, ButtonLoadPosition, ButtonMachineBlack, ButtonBackward,
  427.     ButtonFlipView, ButtonSaveGame, ButtonForceMoves, ButtonPause,
  428.     ButtonHint, ButtonSavePosition, ButtonTwoMachines, ButtonEditPosition
  429. } Button;
  430.  
  431. #define PIECE_MENU_SIZE 18
  432. String pieceMenuStrings[PIECE_MENU_SIZE] = {
  433.     "----", "Pawn", "Lance", "Knight", "Silver",
  434.                 "Gold", "Bishop", "Rook",
  435.         "PPawn", "PLance", "PKnight", "PSilver",
  436.         "PBishop", "PRook", "King",
  437.     "----", "Empty square", "Clear board"
  438. };
  439. /* must be in same order as PieceMenuStrings! */
  440. ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
  441.     { (ChessSquare) 0, BlackPawn, BlackLance, BlackKnight, BlackSilver, 
  442.          BlackGold, BlackBishop, BlackRook,
  443.         BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver,
  444.         BlackPBishop, BlackPRook, BlackKing,
  445.          (ChessSquare) 0, EmptySquare, ClearBoard },
  446.     { (ChessSquare) 0, WhitePawn, WhiteLance, WhiteKnight, WhiteSilver, 
  447.          WhiteGold, WhiteBishop, WhiteRook,
  448.         WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver,
  449.         WhitePBishop, WhitePRook, WhiteKing,
  450.          (ChessSquare) 0, EmptySquare, ClearBoard },
  451. };
  452.  
  453. Arg shellArgs[] = {
  454.     { XtNwidth, 0 },
  455.     { XtNheight, 0 },
  456.     { XtNminWidth, 0 },
  457.     { XtNminHeight, 0 },
  458.     { XtNmaxWidth, 0 },
  459.     { XtNmaxHeight, 0 }
  460. };
  461.  
  462. Arg boardArgs[] = {
  463.     { XtNborderWidth, 0 },
  464.     { XtNwidth, LINE_GAP + (BOARD_SIZE+4) * (SMALL_SQUARE_SIZE + LINE_GAP) },
  465.     { XtNheight, LINE_GAP + BOARD_SIZE * (SMALL_SQUARE_SIZE + LINE_GAP) }
  466. };
  467.  
  468. Arg commandsArgs[] = {
  469.     { XtNborderWidth, 0 },
  470.     { XtNdefaultColumns, 4 },
  471.     { XtNforceColumns, True },
  472.     { XtNlist, (XtArgVal) buttonStrings },
  473.     { XtNnumberStrings, XtNumber(buttonStrings) }
  474. };
  475.  
  476. Arg messageArgs[] = {
  477.     { XtNborderWidth, 0 },
  478.     { XtNjustify, (XtArgVal) XtJustifyLeft },
  479.     { XtNlabel, (XtArgVal) "starting..." }
  480. };
  481.  
  482. Arg timerArgs[] = {
  483.     { XtNborderWidth, 0 },
  484.     { XtNjustify, (XtArgVal) XtJustifyLeft }
  485. };
  486.  
  487. Arg nameArgs[] = {
  488.     { XtNborderWidth, 0 },
  489.     { XtNjustify, (XtArgVal) XtJustifyLeft }
  490. };
  491.  
  492. typedef struct {
  493.     Pixel blackPieceColor;
  494.     Pixel whitePieceColor;
  495.     Pixel lightSquareColor;
  496.     Pixel darkSquareColor;
  497.     int movesPerSession;
  498.     String initString;
  499.     String blackString;
  500.     String whiteString;
  501.     String firstChessProgram;
  502.     String secondChessProgram;
  503.     Boolean noChessProgram;
  504.     String firstHost;
  505.     String secondHost;
  506.     String reverseBigSolidBitmap;
  507.     String reverseSmallSolidBitmap;
  508.     String normalBigSolidBitmap;
  509.     String normalSmallSolidBitmap;
  510.     String reversePawnBitmap;
  511.     String reverseLanceBitmap;
  512.     String reverseKnightBitmap;
  513.     String reverseSilverBitmap;
  514.     String reverseGoldBitmap;
  515.     String reverseRookBitmap;
  516.     String reverseBishopBitmap;
  517.     String reversePPawnBitmap;
  518.     String reversePLanceBitmap;
  519.     String reversePKnightBitmap;
  520.     String reversePSilverBitmap;
  521.     String reversePBishopBitmap;
  522.     String reversePRookBitmap;
  523.     String reverseKingBitmap;
  524.     String normalPawnBitmap;
  525.     String normalLanceBitmap;
  526.     String normalKnightBitmap;
  527.     String normalSilverBitmap;
  528.     String normalGoldBitmap;
  529.     String normalRookBitmap;
  530.     String normalBishopBitmap;
  531.     String normalPPawnBitmap;
  532.     String normalPLanceBitmap;
  533.     String normalPKnightBitmap;
  534.     String normalPSilverBitmap;
  535.     String normalPBishopBitmap;
  536.     String normalPRookBitmap;
  537.     String normalKingBitmap;
  538.     String remoteShell;
  539.     float timeDelay;
  540.     String timeControl;
  541.     String loadGameFile;
  542.     String loadPositionFile;
  543.     String saveGameFile;
  544.     String savePositionFile;
  545.     String matchMode;
  546.     Boolean monoMode;
  547.     Boolean debugMode;
  548.     Boolean clockMode;
  549.     String boardSize;
  550.     Boolean Iconic;
  551.     String searchTime;
  552.     int searchDepth;
  553.         Boolean showCoords;
  554.     String coordFont;
  555. } AppData, *AppDataPtr;
  556.  
  557. AppData appData;
  558.  
  559. XtResource clientResources[] = {
  560.     {
  561.         "blackPieceColor", "BlackPieceColor", XtRPixel, sizeof(Pixel),
  562.         XtOffset(AppDataPtr, blackPieceColor), XtRString,
  563.         BLACK_PIECE_COLOR
  564.     }, {
  565.         "whitePieceColor", "WhitePieceColor", XtRPixel, sizeof(Pixel),
  566.         XtOffset(AppDataPtr, whitePieceColor), XtRString,
  567.         WHITE_PIECE_COLOR
  568.     }, {
  569.         "lightSquareColor", "LightSquareColor", XtRPixel,
  570.         sizeof(Pixel), XtOffset(AppDataPtr, lightSquareColor),
  571.         XtRString, LIGHT_SQUARE_COLOR
  572.     }, {
  573.         "darkSquareColor", "DarkSquareColor", XtRPixel, sizeof(Pixel),
  574.         XtOffset(AppDataPtr, darkSquareColor), XtRString,
  575.         DARK_SQUARE_COLOR
  576.     }, {
  577.         "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
  578.         XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
  579.         (XtPointer) MOVES_PER_SESSION
  580.     }, {
  581.         "initString", "initString", XtRString, sizeof(String),
  582.         XtOffset(AppDataPtr, initString), XtRString, INIT_STRING
  583.     }, {
  584.         "blackString", "blackString", XtRString, sizeof(String),
  585.         XtOffset(AppDataPtr, blackString), XtRString, BLACK_STRING
  586.     }, {
  587.         "whiteString", "whiteString", XtRString, sizeof(String),
  588.         XtOffset(AppDataPtr, whiteString), XtRString, WHITE_STRING
  589.     }, {
  590.         "firstChessProgram", "firstChessProgram", XtRString,
  591.         sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
  592.         XtRString, FIRST_CHESS_PROGRAM
  593.     }, {
  594.         "secondChessProgram", "secondChessProgram", XtRString,
  595.         sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
  596.         XtRString, SECOND_CHESS_PROGRAM
  597.     }, {
  598.         "noChessProgram", "noChessProgram", XtRBoolean,
  599.         sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
  600.         XtRImmediate, (XtPointer) False
  601.     }, {
  602.         "firstHost", "firstHost", XtRString, sizeof(String),
  603.         XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST
  604.     }, {
  605.         "secondHost", "secondHost", XtRString, sizeof(String),
  606.         XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST
  607.     }, {
  608.         "reversePawnBitmap", "reversePawnBitmap", XtRString,
  609.         sizeof(String), XtOffset(AppDataPtr, reversePawnBitmap),
  610.         XtRString, NULL
  611.     }, {
  612.         "reverseLanceBitmap", "reverseLanceBitmap", XtRString,
  613.         sizeof(String), XtOffset(AppDataPtr, reverseLanceBitmap),
  614.         XtRString, NULL
  615.     }, {
  616.         "reverseKnightBitmap", "reverseKnightBitmap", XtRString,
  617.         sizeof(String), XtOffset(AppDataPtr, reverseKnightBitmap),
  618.         XtRString, NULL
  619.     }, {
  620.         "reverseSilverBitmap", "reverseSilverBitmap", XtRString,
  621.         sizeof(String), XtOffset(AppDataPtr, reverseSilverBitmap),
  622.         XtRString, NULL
  623.     }, {
  624.         "reverseGoldBitmap", "reverseGoldBitmap", XtRString,
  625.         sizeof(String), XtOffset(AppDataPtr, reverseGoldBitmap),
  626.         XtRString, NULL
  627.     }, {
  628.         "reverseRookBitmap", "reverseRookBitmap", XtRString,
  629.         sizeof(String), XtOffset(AppDataPtr, reverseRookBitmap),
  630.         XtRString, NULL
  631.     }, {
  632.         "reverseBishopBitmap", "reverseBishopBitmap", XtRString,
  633.         sizeof(String), XtOffset(AppDataPtr, reverseBishopBitmap),
  634.         XtRString, NULL
  635.     }, {
  636.         "reversePPawnBitmap", "reversePPawnBitmap", XtRString,
  637.         sizeof(String), XtOffset(AppDataPtr, reversePPawnBitmap),
  638.         XtRString, NULL
  639.     }, {
  640.         "reversePLanceBitmap", "reversePLanceBitmap", XtRString,
  641.         sizeof(String), XtOffset(AppDataPtr, reversePLanceBitmap),
  642.         XtRString, NULL
  643.     }, {
  644.         "reversePKnightBitmap", "reversePKnightBitmap", XtRString,
  645.         sizeof(String), XtOffset(AppDataPtr, reversePKnightBitmap),
  646.         XtRString, NULL
  647.     }, {
  648.         "reversePSilverBitmap", "reversePSilverBitmap", XtRString,
  649.         sizeof(String), XtOffset(AppDataPtr, reversePSilverBitmap),
  650.         XtRString, NULL
  651.     }, {
  652.         "reversePRookBitmap", "reversePRookBitmap", XtRString,
  653.         sizeof(String), XtOffset(AppDataPtr, reversePRookBitmap),
  654.         XtRString, NULL
  655.     }, {
  656.         "reversePBishopBitmap", "reversePBishopBitmap", XtRString,
  657.         sizeof(String), XtOffset(AppDataPtr, reversePBishopBitmap),
  658.         XtRString, NULL
  659.     }, {
  660.         "reverseKingBitmap", "reverseKingBitmap", XtRString,
  661.         sizeof(String), XtOffset(AppDataPtr, reverseKingBitmap),
  662.         XtRString, NULL
  663.     }, {
  664.         "normalPawnBitmap", "normalPawnBitmap", XtRString,
  665.         sizeof(String), XtOffset(AppDataPtr, normalPawnBitmap),
  666.         XtRString, NULL
  667.     }, {
  668.         "normalLanceBitmap", "normalLanceBitmap", XtRString,
  669.         sizeof(String), XtOffset(AppDataPtr, normalLanceBitmap),
  670.         XtRString, NULL
  671.     }, {
  672.         "normalKnightBitmap", "normalKnightBitmap", XtRString,
  673.         sizeof(String), XtOffset(AppDataPtr, normalKnightBitmap),
  674.         XtRString, NULL
  675.     }, {
  676.         "normalSilverBitmap", "normalSilverBitmap", XtRString,
  677.         sizeof(String), XtOffset(AppDataPtr, normalSilverBitmap),
  678.         XtRString, NULL
  679.     }, {
  680.         "normalGoldBitmap", "normalGoldBitmap", XtRString,
  681.         sizeof(String), XtOffset(AppDataPtr, normalGoldBitmap),
  682.         XtRString, NULL
  683.     }, {
  684.         "normalBishopBitmap", "normalBishopBitmap", XtRString,
  685.         sizeof(String), XtOffset(AppDataPtr, normalBishopBitmap),
  686.         XtRString, NULL
  687.     }, {
  688.         "normalRookBitmap", "normalRookBitmap", XtRString,
  689.         sizeof(String), XtOffset(AppDataPtr, normalRookBitmap),
  690.         XtRString, NULL
  691.     }, {
  692.         "normalPPawnBitmap", "normalPPawnBitmap", XtRString,
  693.         sizeof(String), XtOffset(AppDataPtr, normalPPawnBitmap),
  694.         XtRString, NULL
  695.     }, {
  696.         "normalPLanceBitmap", "normalPLanceBitmap", XtRString,
  697.         sizeof(String), XtOffset(AppDataPtr, normalPLanceBitmap),
  698.         XtRString, NULL
  699.     }, {
  700.         "normalPKnightBitmap", "normalPKnightBitmap", XtRString,
  701.         sizeof(String), XtOffset(AppDataPtr, normalPKnightBitmap),
  702.         XtRString, NULL
  703.     }, {
  704.         "normalPSilverBitmap", "normalPSilverBitmap", XtRString,
  705.         sizeof(String), XtOffset(AppDataPtr, normalPSilverBitmap),
  706.         XtRString, NULL
  707.     }, {
  708.         "normalPBishopBitmap", "normalPBishopBitmap", XtRString,
  709.         sizeof(String), XtOffset(AppDataPtr, normalPBishopBitmap),
  710.         XtRString, NULL
  711.     }, {
  712.         "normalPRookBitmap", "normalPRookBitmap", XtRString,
  713.         sizeof(String), XtOffset(AppDataPtr, normalPRookBitmap),
  714.         XtRString, NULL
  715.     }, {
  716.         "normalKingBitmap", "normalKingBitmap", XtRString,
  717.         sizeof(String), XtOffset(AppDataPtr, normalKingBitmap),
  718.         XtRString, NULL
  719.     }, {
  720.         "remoteShell", "remoteShell", XtRString, sizeof(String),
  721.         XtOffset(AppDataPtr, remoteShell), XtRString, "rsh"
  722.     }, {
  723.         "timeDelay", "timeDelay", XtRFloat, sizeof(float),
  724.         XtOffset(AppDataPtr, timeDelay), XtRString,
  725.         (XtPointer) TIME_DELAY
  726.     }, {
  727.         "timeControl", "timeControl", XtRString, sizeof(String),
  728.         XtOffset(AppDataPtr, timeControl), XtRString,
  729.         (XtPointer) TIME_CONTROL
  730.     }, {
  731.         "loadGameFile", "loadGameFile", XtRString, sizeof(String),
  732.         XtOffset(AppDataPtr, loadGameFile), XtRString, NULL
  733.     }, {
  734.         "loadPositionFile", "loadPositionFile", XtRString,
  735.         sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
  736.         XtRString, NULL
  737.     }, {
  738.         "saveGameFile", "saveGameFile", XtRString, sizeof(String),
  739.         XtOffset(AppDataPtr, saveGameFile), XtRString, ""
  740.     }, {
  741.         "savePositionFile", "savePositionFile", XtRString,
  742.         sizeof(String), XtOffset(AppDataPtr, savePositionFile),
  743.         XtRString, ""
  744.     }, {
  745.         "matchMode", "matchMode", XtRString, sizeof(String),
  746.         XtOffset(AppDataPtr, matchMode), XtRString, MATCH_MODE
  747.     }, {
  748.         "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
  749.         XtOffset(AppDataPtr, monoMode), XtRImmediate,
  750.         (XtPointer) False
  751.     }, {
  752.         "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
  753.         XtOffset(AppDataPtr, debugMode), XtRImmediate,
  754.         (XtPointer) False
  755.     }, {
  756.         "Iconic", "Iconic", XtRBoolean, sizeof(Boolean),
  757.         XtOffset(AppDataPtr, Iconic), XtRImmediate,
  758.         (XtPointer) False
  759.     }, {
  760.         "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
  761.         XtOffset(AppDataPtr, clockMode), XtRImmediate,
  762.         (XtPointer) True
  763.     }, {
  764.         "boardSize", "boardSize", XtRString, sizeof(String),
  765.         XtOffset(AppDataPtr, boardSize), XtRString, DEFAULT_SIZE
  766.     }, {
  767.         "searchTime", "searchTime", XtRString, sizeof(String),
  768.         XtOffset(AppDataPtr, searchTime), XtRString,
  769.         (XtPointer) NULL
  770.     }, {
  771.         "searchDepth", "searchDepth", XtRInt, sizeof(int),
  772.         XtOffset(AppDataPtr, searchDepth), XtRImmediate, 
  773.         (XtPointer) 0
  774.     }, {
  775.         "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
  776.         XtOffset(AppDataPtr, showCoords), XtRImmediate,
  777.         (XtPointer) False
  778.     }, {
  779.         "coordFont", "coordFont", XtRString, sizeof(String),
  780.         XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT
  781.     }
  782. };
  783.  
  784. Pixmap *pieceToReverse[] = {
  785.     &reversePawnBitmap, &reverseLanceBitmap, &reverseKnightBitmap,
  786.     &reverseSilverBitmap, &reverseGoldBitmap, &reverseBishopBitmap,
  787.         &reverseRookBitmap, &reversePPawnBitmap, &reversePLanceBitmap,
  788.         &reversePKnightBitmap, &reversePSilverBitmap, &reversePBishopBitmap,
  789.         &reversePRookBitmap, &reverseKingBitmap,
  790.     &reversePawnBitmap, &reverseLanceBitmap, &reverseKnightBitmap,
  791.     &reverseSilverBitmap, &reverseGoldBitmap, &reverseBishopBitmap,
  792.         &reverseRookBitmap, &reversePPawnBitmap, &reversePLanceBitmap,
  793.         &reversePKnightBitmap, &reversePSilverBitmap, &reversePBishopBitmap,
  794.         &reversePRookBitmap, &reverseKingBitmap
  795. };
  796.  
  797. Pixmap *pieceToNormal[] = {
  798.     &normalPawnBitmap, &normalLanceBitmap, &normalKnightBitmap,
  799.     &normalSilverBitmap, &normalGoldBitmap, &normalBishopBitmap,
  800.         &normalRookBitmap, &normalPPawnBitmap, &normalPLanceBitmap,
  801.         &normalPKnightBitmap, &normalPSilverBitmap, &normalPBishopBitmap,
  802.         &normalPRookBitmap, &normalKingBitmap,
  803.     &normalPawnBitmap, &normalLanceBitmap, &normalKnightBitmap,
  804.     &normalSilverBitmap, &normalGoldBitmap, &normalBishopBitmap,
  805.         &normalRookBitmap, &normalPPawnBitmap, &normalPLanceBitmap,
  806.         &normalPKnightBitmap, &normalPSilverBitmap, &normalPBishopBitmap,
  807.         &normalPRookBitmap, &normalKingBitmap
  808. };
  809.  
  810. Pixmap *pieceToReverseSolid[] = {
  811.     &reverseSmallSolidBitmap, &reverseSmallSolidBitmap, &reverseSmallSolidBitmap,
  812.     &reverseBigSolidBitmap, &reverseBigSolidBitmap, &reverseBigSolidBitmap,
  813.         &reverseBigSolidBitmap, &reverseSmallSolidBitmap, &reverseSmallSolidBitmap,
  814.         &reverseSmallSolidBitmap, &reverseBigSolidBitmap, &reverseBigSolidBitmap,
  815.         &reverseBigSolidBitmap, &reverseBigSolidBitmap,
  816.     &reverseSmallSolidBitmap, &reverseSmallSolidBitmap, &reverseSmallSolidBitmap,
  817.     &reverseBigSolidBitmap, &reverseBigSolidBitmap, &reverseBigSolidBitmap,
  818.         &reverseBigSolidBitmap, &reverseSmallSolidBitmap, &reverseSmallSolidBitmap,
  819.         &reverseSmallSolidBitmap, &reverseBigSolidBitmap, &reverseBigSolidBitmap,
  820.         &reverseBigSolidBitmap, &reverseBigSolidBitmap,
  821. };
  822.  
  823. Pixmap *pieceToNormalSolid[] = {
  824.     &normalSmallSolidBitmap, &normalSmallSolidBitmap, &normalSmallSolidBitmap,
  825.     &normalBigSolidBitmap, &normalBigSolidBitmap, &normalBigSolidBitmap,
  826.         &normalBigSolidBitmap, &normalSmallSolidBitmap, &normalSmallSolidBitmap,
  827.         &normalSmallSolidBitmap, &normalBigSolidBitmap, &normalBigSolidBitmap,
  828.         &normalBigSolidBitmap, &normalBigSolidBitmap,
  829.     &normalSmallSolidBitmap, &normalSmallSolidBitmap, &normalSmallSolidBitmap,
  830.     &normalBigSolidBitmap, &normalBigSolidBitmap, &normalBigSolidBitmap,
  831.         &normalBigSolidBitmap, &normalSmallSolidBitmap, &normalSmallSolidBitmap,
  832.         &normalSmallSolidBitmap, &normalBigSolidBitmap, &normalBigSolidBitmap,
  833.         &normalBigSolidBitmap, &normalBigSolidBitmap,
  834. };
  835.  
  836. int pieceIsPromoted[] = {
  837.      False, False, False, False, False, False, False,  
  838.         True,  True,  True,  True,  True,  True,  False,
  839.      False, False, False, False, False, False, False,  
  840.         True,  True,  True,  True,  True,  True,  False,
  841.         False
  842. };
  843.  
  844. int piecePromotable[] = {
  845.      True,  True,  True,  True,  False, True,  True,  
  846.      False, False, False, False, False, False, False,  
  847.      True,  True,  True,  True,  False, True,  True,  
  848.      False, False, False, False, False, False, False,  
  849.         False
  850. };
  851.  
  852. char pieceToChar[] = {                               
  853.     'P', 'L', 'N', 'S', 'G', 'B', 'R', 'P', 'L', 'N', 'S', 'B', 'R', 'K',
  854.     'p', 'l', 'n', 's', 'g', 'b', 'r', 'p', 'l', 'n', 's', 'b', 'r', 'k', 
  855.         '.'
  856. };  
  857.  
  858.  
  859. #ifdef WESTERN_BITMAPS
  860.  
  861. int pieceisWhite[] = {
  862.      True,  True,  True,  True,  True, True,  True,  
  863.      True, True, True, True, True, True, True,  
  864.      False, False, False, False, False, False, False,  
  865.      False, False, False, False, False, False, False,  
  866.         False
  867. };
  868.  
  869. #endif
  870.  
  871.  
  872. ChessSquare pieceToPromoted[] = {                               
  873.     BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver, BlackGold,
  874.     BlackPBishop, BlackPRook,
  875.     BlackPPawn, BlackPLance, BlackPKnight, BlackPSilver, 
  876.     BlackPBishop, BlackPRook, BlackKing,
  877.     WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver, WhiteGold,
  878.     WhitePBishop, WhitePRook,
  879.     WhitePPawn, WhitePLance, WhitePKnight, WhitePSilver, 
  880.     WhitePBishop, WhitePRook, WhiteKing
  881. };
  882.  
  883. XrmOptionDescRec shellOptions[] = {
  884.     { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
  885.     { "-wpc", "blackPieceColor", XrmoptionSepArg, NULL },
  886.     { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
  887.     { "-bpc", "whitePieceColor", XrmoptionSepArg, NULL },
  888.     { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
  889.     { "-lsc", "lightSquareColor", XrmoptionSepArg, NULL },
  890.     { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
  891.     { "-dsc", "darkSquareColor", XrmoptionSepArg, NULL },
  892.     { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
  893.     { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
  894.     { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
  895.     { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
  896.     { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
  897.     { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
  898.     { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
  899.     { "-ncp", "noChessProgram", XrmoptionSepArg, NULL },
  900.     { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
  901.     { "-fh", "firstHost", XrmoptionSepArg, NULL },
  902.     { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
  903.     { "-sh", "secondHost", XrmoptionSepArg, NULL },
  904.     { "-reversePawnBitmap", "reversePawnBitmap", XrmoptionSepArg, NULL },
  905.     { "-rpb", "reversePawnBitmap", XrmoptionSepArg, NULL },
  906.     { "-reverseLanceBitmap", "reverseLanceBitmap", XrmoptionSepArg, NULL },
  907.     { "-rlb", "reverseLanceBitmap", XrmoptionSepArg, NULL },
  908.     { "-reverseKnightBitmap", "reverseKnightBitmap", XrmoptionSepArg, NULL },
  909.     { "-rnb", "reverseKnightBitmap", XrmoptionSepArg, NULL },
  910.     { "-reverseSilverBitmap", "reverseSilverBitmap", XrmoptionSepArg, NULL },
  911.     { "-rsb", "reverseSilverBitmap", XrmoptionSepArg, NULL },
  912.     { "-reverseGoldBitmap", "reverseGoldBitmap", XrmoptionSepArg, NULL },
  913.     { "-rgb", "reverseGoldBitmap", XrmoptionSepArg, NULL },
  914.     { "-reverseRookBitmap", "reverseRookBitmap", XrmoptionSepArg, NULL },
  915.     { "-rrb", "reverseRookBitmap", XrmoptionSepArg, NULL },
  916.     { "-reverseBishopBitmap", "reverseBishopBitmap", XrmoptionSepArg, NULL },
  917.     { "-rbb", "reverseBishopBitmap", XrmoptionSepArg, NULL },
  918.     { "-reversePPawnBitmap", "reversePPawnBitmap", XrmoptionSepArg, NULL },
  919.     { "-rppb", "reversePPawnBitmap", XrmoptionSepArg, NULL },
  920.     { "-reversePLanceBitmap", "reversePLanceBitmap", XrmoptionSepArg, NULL },
  921.     { "-rplb", "reversePLanceBitmap", XrmoptionSepArg, NULL },
  922.     { "-reversePKnightBitmap", "reversePKnightBitmap", XrmoptionSepArg, NULL },
  923.     { "-rpnb", "reversePKnightBitmap", XrmoptionSepArg, NULL },
  924.     { "-reversePSilverBitmap", "reversePSilverBitmap", XrmoptionSepArg, NULL },
  925.     { "-rpsb", "reversePSilverBitmap", XrmoptionSepArg, NULL },
  926.     { "-reversePRookBitmap", "reversePRookBitmap", XrmoptionSepArg, NULL },
  927.     { "-rprb", "reversePRookBitmap", XrmoptionSepArg, NULL },
  928.     { "-reversePBishopBitmap", "reversePBishopBitmap", XrmoptionSepArg, NULL },
  929.     { "-rpbb", "reversePBishopBitmap", XrmoptionSepArg, NULL },
  930.     { "-reverseKingBitmap", "reverseKingBitmap", XrmoptionSepArg, NULL },
  931.     { "-rkb", "reverseKingBitmap", XrmoptionSepArg, NULL },
  932.     { "-outlinePawnBitmap", "outlinePawnBitmap", XrmoptionSepArg, NULL },
  933.     { "-opb", "normalPawnBitmap", XrmoptionSepArg, NULL },
  934.     { "-normalLanceBitmap", "normalLanceBitmap", XrmoptionSepArg, NULL },
  935.     { "-olb", "normalLanceBitmap", XrmoptionSepArg, NULL },
  936.     { "-normalKnightBitmap", "normalKnightBitmap", XrmoptionSepArg, NULL },
  937.     { "-onb", "normalKnightBitmap", XrmoptionSepArg, NULL },
  938.     { "-normalSilverBitmap", "normalSilverBitmap", XrmoptionSepArg, NULL },
  939.     { "-osb", "normalSilverBitmap", XrmoptionSepArg, NULL },
  940.     { "-normalGoldBitmap", "normalGoldBitmap", XrmoptionSepArg, NULL },
  941.     { "-ogb", "normalGoldBitmap", XrmoptionSepArg, NULL },
  942.     { "-normalRookBitmap", "normalRookBitmap", XrmoptionSepArg, NULL },
  943.     { "-orb", "normalRookBitmap", XrmoptionSepArg, NULL },
  944.     { "-normalBishopBitmap", "normalBishopBitmap", XrmoptionSepArg, NULL },
  945.     { "-obb", "normalBishopBitmap", XrmoptionSepArg, NULL },
  946.     { "-normalPPawnBitmap", "normalPPawnBitmap", XrmoptionSepArg, NULL },
  947.     { "-oppb", "normalPPawnBitmap", XrmoptionSepArg, NULL },
  948.     { "-normalPLanceBitmap", "normalPLanceBitmap", XrmoptionSepArg, NULL },
  949.     { "-oplb", "normalPLanceBitmap", XrmoptionSepArg, NULL },
  950.     { "-normalPKnightBitmap", "normalPKnightBitmap", XrmoptionSepArg, NULL },
  951.     { "-opnb", "normalPKnightBitmap", XrmoptionSepArg, NULL },
  952.     { "-normalPSilverBitmap", "normalPSilverBitmap", XrmoptionSepArg, NULL },
  953.     { "-opsb", "normalPSilverBitmap", XrmoptionSepArg, NULL },
  954.     { "-normalPRookBitmap", "normalPRookBitmap", XrmoptionSepArg, NULL },
  955.     { "-oprb", "normalPRookBitmap", XrmoptionSepArg, NULL },
  956.     { "-normalPBishopBitmap", "normalPBishopBitmap", XrmoptionSepArg, NULL },
  957.     { "-opbb", "normalPBishopBitmap", XrmoptionSepArg, NULL },
  958.     { "-normalKingBitmap", "normalKingBitmap", XrmoptionSepArg, NULL },
  959.     { "-okb", "outlineKingBitmap", XrmoptionSepArg, NULL },
  960.     { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
  961.     { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
  962.     { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
  963.     { "-td", "timeDelay", XrmoptionSepArg, NULL },
  964.     { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
  965.     { "-tc", "timeControl", XrmoptionSepArg, NULL },
  966.     { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
  967.     { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
  968.     { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
  969.     { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
  970.     { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
  971.     { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
  972.     { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
  973.     { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
  974.     { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
  975.     { "-mm", "matchMode", XrmoptionSepArg, NULL },
  976.     { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
  977.     { "-mono", "monoMode", XrmoptionSepArg, NULL },
  978.     { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
  979.     { "-debug", "debugMode", XrmoptionSepArg, NULL },
  980.     { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
  981.     { "-clock", "clockMode", XrmoptionSepArg, NULL },
  982.     { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
  983.     { "-size", "boardSize", XrmoptionSepArg, NULL },
  984.     { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
  985.     { "-st", "searchTime", XrmoptionSepArg, NULL },
  986.     { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
  987.     { "-sd", "searchDepth", XrmoptionSepArg, NULL },
  988.     { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
  989.     { "-coords", "showCoords", XrmoptionSepArg, NULL },
  990.     { "-iconic", "Iconic", XrmoptionNoArg, "True" }
  991. };
  992.  
  993. XtActionsRec boardActions[] = {
  994.     { "DrawPosition", (XtActionProc) DrawPosition },
  995.     { "HandleUserMove", (XtActionProc) HandleUserMove },
  996.     { "ResetProc", (XtActionProc) ResetProc },
  997.     { "ResetFileProc", (XtActionProc) ResetFileProc },
  998.     { "GameProc", (XtActionProc) GameProc },
  999.     { "QuitProc", (XtActionProc) QuitProc },
  1000.     { "ForwardProc", (XtActionProc) ForwardProc },
  1001.     { "BackwardProc", (XtActionProc) BackwardProc },
  1002.     { "PauseProc", (XtActionProc) PauseProc },
  1003.     { "Iconify", (XtActionProc) Iconify },
  1004.     { "FileNameAction", (XtActionProc) FileNameAction },
  1005.     { "PieceMenuPopup", (XtActionProc) PieceMenuPopup },
  1006.     { "SetBlackToPlay", (XtActionProc) SetBlackToPlay },
  1007.     { "SetWhiteToPlay", (XtActionProc) SetWhiteToPlay }
  1008. };
  1009.  
  1010. char translationsTable[] =
  1011.     "<Expose>: DrawPosition() \n \
  1012.      <Btn1Down>: HandleUserMove() \n \
  1013.      <Btn1Up>: HandleUserMove() \n \
  1014.      <Btn2Down>: XawPositionSimpleMenu(menuW) PieceMenuPopup(menuW) \n \
  1015.      <Btn3Down>: XawPositionSimpleMenu(menuB) PieceMenuPopup(menuB) \n \
  1016.      <Key>r: ResetFileProc() ResetProc() \n \
  1017.      <Key>R: ResetFileProc() ResetProc() \n \
  1018.      <Key>g: GameProc() \n \
  1019.      <Key>G: GameProc() \n \
  1020.      <Key>q: QuitProc() \n \
  1021.      <Key>Q: QuitProc() \n \
  1022.      <Message>WM_PROTOCOLS: QuitProc() \n \
  1023.      <Key>f: ForwardProc() \n \
  1024.      <Key>F: ForwardProc() \n \
  1025.      <Key>b: BackwardProc() \n \
  1026.      <Key>B: BackwardProc() \n \
  1027.      <Key>p: PauseProc() \n \
  1028.      <Key>P: PauseProc() \n \
  1029.      <Key>i: Iconify() \n \
  1030.      <Key>I: Iconify() \n \
  1031.      <Key>c: Iconify() \n \
  1032.      <Key>C: Iconify() \n";
  1033.  
  1034. char blackTranslations[] = "<BtnDown>: SetBlackToPlay()\n";
  1035. char whiteTranslations[] = "<BtnDown>: SetWhiteToPlay()\n";
  1036.  
  1037. String xshogiResources[] = {
  1038.     "*font: -*-helvetica-medium-o-normal--*-140-*-*-*-*-*-*\n",
  1039.     "*Dialog*value.translations: #override \\n <Key>Return: FileNameAction()",
  1040.     NULL
  1041. };
  1042.  
  1043. void
  1044. main(argc, argv)
  1045.     int argc;
  1046.     char **argv;
  1047. {
  1048.     XSetWindowAttributes window_attributes;
  1049.     char buf[MSG_SIZ];
  1050.     Arg args[3];
  1051.     Dimension timerWidth, boardWidth, commandsWidth, w, h;
  1052.  
  1053.     setbuf(stdout, NULL); setbuf(stderr, NULL);
  1054.  
  1055.     programName = strrchr(argv[0], '/');
  1056.     if (programName == NULL)
  1057.       programName = argv[0];
  1058.     else
  1059.       programName++;
  1060.  
  1061.     shellWidget = XtAppInitialize(&appContext, "XShogi", shellOptions,
  1062.         XtNumber(shellOptions), &argc, argv, xshogiResources, NULL, 0);
  1063.     if (argc > 1)
  1064.         Usage();
  1065.  
  1066.     if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
  1067.         chessDir = ".";
  1068.     } else {
  1069.         if (chdir(chessDir) != 0) {
  1070.             fprintf(stderr, "%s: can't cd to CHESSDIR\n",
  1071.                 programName);
  1072.             perror(chessDir);
  1073.             exit(1);
  1074.         }
  1075.     }
  1076.  
  1077.     XtGetApplicationResources(shellWidget, &appData, clientResources,
  1078.         XtNumber(clientResources), NULL, 0);
  1079.  
  1080.     xshogiDebug = appData.debugMode;
  1081.  
  1082.     /*
  1083.      * Determine matchMode state -- poor man's resource converter
  1084.      */
  1085.     if (StrCaseCmp(appData.matchMode, "Init") == 0)
  1086.         matchMode = MatchInit;
  1087.     else if (StrCaseCmp(appData.matchMode, "Position") == 0)
  1088.         matchMode = MatchPosition;
  1089.     else if (StrCaseCmp(appData.matchMode, "Opening") == 0)
  1090.         matchMode = MatchOpening;
  1091.     else if (StrCaseCmp(appData.matchMode, "False") == 0)
  1092.         matchMode = MatchFalse;
  1093.     else {
  1094.         fprintf(stderr, "%s: bad matchMode option %s\n",
  1095.             programName, appData.matchMode);
  1096.         Usage();
  1097.     }
  1098.  
  1099.     /*
  1100.      * Parse timeControl resource
  1101.      */
  1102.     if (appData.timeControl != NULL) {
  1103.         int min, sec, matched;
  1104.  
  1105.         matched = sscanf(appData.timeControl, "%d:%d", &min, &sec);
  1106.         if (matched == 1) {
  1107.             timeControl = min * 60 * 1000;
  1108.         } else if (matched == 2) {
  1109.             timeControl = (min * 60 + sec) * 1000;
  1110.         } else {
  1111.             fprintf(stderr, "%s: bad timeControl option %s\n",
  1112.                 programName, appData.timeControl);
  1113.             Usage();
  1114.         }
  1115.     }
  1116.  
  1117.     /*
  1118.      * Parse searchTime resource
  1119.      */
  1120.     if (appData.searchTime != NULL) {
  1121.         int min, sec, matched;
  1122.  
  1123.         matched = sscanf(appData.searchTime, "%d:%d", &min, &sec);
  1124.         if (matched == 1) {
  1125.             searchTime = min * 60;
  1126.         } else if (matched == 2) {
  1127.             searchTime = min * 60 + sec;
  1128.         } else {
  1129.             fprintf(stderr, "%s: bad searchTime option %s\n",
  1130.                 programName, appData.searchTime);
  1131.             Usage();
  1132.         }
  1133.     }
  1134.  
  1135.     /*
  1136.      * Determine boardSize
  1137.      */
  1138.     if (StrCaseCmp(appData.boardSize, "Large") == 0)
  1139.         boardSize = Large;
  1140.     else if (StrCaseCmp(appData.boardSize, "Medium") == 0)
  1141.         boardSize = Medium;
  1142.     else if (StrCaseCmp(appData.boardSize, "Small") == 0)
  1143.         boardSize = Small;
  1144.     else {
  1145.         fprintf(stderr, "%s: bad boardSize option %s\n",
  1146.             programName, appData.boardSize);
  1147.         Usage();
  1148.     }
  1149.  
  1150.     xDisplay = XtDisplay(shellWidget);
  1151.     xScreen = DefaultScreen(xDisplay);
  1152.     if (((DisplayWidth(xDisplay, xScreen) < 800)
  1153.          ||    (DisplayHeight(xDisplay, xScreen) < 800))
  1154.         && (boardSize == Large)) {
  1155.         boardSize = Medium;
  1156.     }
  1157.  
  1158.     switch (boardSize) {
  1159.           case Small:
  1160.         squareSize = SMALL_SQUARE_SIZE;
  1161.         break;
  1162.           case Medium:
  1163.         squareSize = MEDIUM_SQUARE_SIZE;
  1164.         break;
  1165.           case Large:
  1166.         squareSize = LARGE_SQUARE_SIZE;
  1167.         break;
  1168.     }
  1169.     boardWidth = LINE_GAP + (BOARD_SIZE+4) * (squareSize + LINE_GAP);
  1170.     XtSetArg(boardArgs[1], XtNwidth, boardWidth);
  1171.     XtSetArg(boardArgs[2], XtNheight,
  1172.          LINE_GAP + BOARD_SIZE * (squareSize + LINE_GAP));
  1173.  
  1174.         if ((appData.searchTime != NULL) || (appData.searchDepth > 0)
  1175.         || appData.noChessProgram)
  1176.       appData.clockMode = False;
  1177.  
  1178.     /*
  1179.      * Detect if there are not enough colors are available and adapt.
  1180.      */
  1181.     if (DefaultDepth(xDisplay, xScreen) <= 2)
  1182.         appData.monoMode = True;
  1183.  
  1184.     /*
  1185.      * widget hierarchy
  1186.      */
  1187.     formWidget = XtCreateManagedWidget("form",
  1188.         formWidgetClass, shellWidget, NULL, 0);
  1189.  
  1190.         widgetList[0] = blackTimerWidget =
  1191.           XtCreateWidget("black time:", labelWidgetClass,
  1192.                  formWidget, timerArgs, XtNumber(timerArgs));
  1193.  
  1194.         widgetList[1] = whiteTimerWidget =
  1195.           XtCreateWidget("white time:", labelWidgetClass,
  1196.                  formWidget, timerArgs, XtNumber(timerArgs));
  1197.  
  1198.         widgetList[2] = nameWidget =
  1199.           XtCreateWidget("", labelWidgetClass,
  1200.                  formWidget, nameArgs, XtNumber(nameArgs));
  1201.  
  1202.         widgetList[3] = messageWidget =
  1203.           XtCreateWidget("message", labelWidgetClass, formWidget,
  1204.                  messageArgs, XtNumber(messageArgs));
  1205.  
  1206.         widgetList[4] = commandsWidget =
  1207.           XtCreateWidget("commands", listWidgetClass, formWidget,
  1208.                  commandsArgs, XtNumber(commandsArgs));
  1209.  
  1210.             widgetList[5] = boardWidget =
  1211.           XtCreateWidget("board", widgetClass, formWidget,
  1212.                  boardArgs, XtNumber(boardArgs));
  1213.  
  1214.     XtManageChildren(widgetList, XtNumber(widgetList));
  1215.  
  1216.     /*
  1217.      * Calculate the width of the timer labels.
  1218.      */
  1219.     XtSetArg(args[0], XtNfont, &labelFont);
  1220.     XtGetValues(blackTimerWidget, args, 1);
  1221.     if (appData.clockMode) {
  1222.         sprintf(buf, "Black: %s ", TimeString(timeControl));
  1223.         timerWidth = XTextWidth(labelFont, buf, strlen(buf) - 1);
  1224.     } else
  1225.         timerWidth = XTextWidth(labelFont, "Black  ", 7);
  1226.     XtSetArg(args[0], XtNwidth, timerWidth);
  1227.     XtSetValues(blackTimerWidget, args, 1);
  1228.     XtSetValues(whiteTimerWidget, args, 1);
  1229.  
  1230.     XtSetArg(args[0], XtNbackground, &timerForegroundPixel);
  1231.     XtSetArg(args[1], XtNforeground, &timerBackgroundPixel);
  1232.     XtGetValues(blackTimerWidget, args, 2);
  1233.  
  1234.     /*
  1235.      * Calculate the width of the name and message labels.
  1236.      */
  1237.     XtSetArg(args[0], XtNwidth, &commandsWidth);
  1238.     XtGetValues(commandsWidget, args, 1);
  1239.         w = (commandsWidth > boardWidth) ? commandsWidth : boardWidth;
  1240.     XtSetArg(args[0], XtNwidth, w - timerWidth*2 - 12);
  1241.     XtSetValues(nameWidget, args, 1);
  1242.     XtSetArg(args[0], XtNwidth, w - 8);
  1243.     XtSetValues(messageWidget, args, 1);
  1244.  
  1245.     /*
  1246.      * formWidget uses these constraints but they are stored
  1247.      * in the children.
  1248.      */
  1249.     XtSetArg(args[0], XtNfromHoriz, blackTimerWidget);
  1250.     XtSetValues(whiteTimerWidget, args, 1);
  1251.     XtSetArg(args[0], XtNfromHoriz, whiteTimerWidget);
  1252.     XtSetValues(nameWidget, args, 1);
  1253.     XtSetArg(args[0], XtNfromVert, blackTimerWidget);
  1254.     XtSetValues(messageWidget, args, 1);
  1255.     XtSetArg(args[0], XtNfromVert, messageWidget);
  1256.     XtSetValues(commandsWidget, args, 1);
  1257.     XtSetArg(args[0], XtNfromVert, commandsWidget);
  1258.     XtSetValues(boardWidget, args, 1);
  1259.  
  1260.     XtRealizeWidget(shellWidget);
  1261.  
  1262.     xBoardWindow = XtWindow(boardWidget);
  1263.  
  1264.     /*
  1265.      * Create an icon.
  1266.      */
  1267.     iconPixmap = XCreateBitmapFromData(xDisplay, XtWindow(shellWidget),
  1268.         icon_bits, icon_width, icon_height);
  1269.     XtSetArg(args[0], XtNiconPixmap, iconPixmap);
  1270.     XtSetValues(shellWidget, args, 1);
  1271.  
  1272.     /*
  1273.      * Create a cursor for the board widget.
  1274.      */
  1275.     window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
  1276.     XChangeWindowAttributes(xDisplay, xBoardWindow,
  1277.         CWCursor, &window_attributes);
  1278.  
  1279.     /*
  1280.      * Inhibit shell resizing.
  1281.      */
  1282.     shellArgs[0].value = (XtArgVal) &w;
  1283.     shellArgs[1].value = (XtArgVal) &h;
  1284.     XtGetValues(shellWidget, shellArgs, 2);
  1285.     shellArgs[4].value = shellArgs[2].value = w;
  1286.     shellArgs[5].value = shellArgs[3].value = h;
  1287.     XtSetValues(shellWidget, &shellArgs[2], 4);
  1288.  
  1289.     black_pixel_is_zero = (XBlackPixel == 0);
  1290.  
  1291.     CreateGCs();
  1292.     CreateGrid();
  1293.     CreatePieces();
  1294.     CreatePieceMenus();
  1295.  
  1296.     XtAddCallback(commandsWidget, XtNcallback, SelectCommand, NULL);
  1297.     XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
  1298.  
  1299.     XtSetArg(args[0], XtNtranslations,
  1300.         XtParseTranslationTable(translationsTable));
  1301.     XtSetValues(boardWidget, &args[0], 1);
  1302.     XtSetArg(args[0], XtNtranslations,
  1303.         XtParseTranslationTable(blackTranslations));
  1304.     XtSetValues(blackTimerWidget, &args[0], 1);
  1305.     XtSetArg(args[0], XtNtranslations,
  1306.         XtParseTranslationTable(whiteTranslations));
  1307.     XtSetValues(whiteTimerWidget, &args[0], 1);
  1308.  
  1309.     XtAddEventHandler(boardWidget, ExposureMask | ButtonPressMask
  1310.         | ButtonReleaseMask | Button1MotionMask | KeyPressMask,
  1311.         False, (XtEventHandler) EventProc, NULL);
  1312.  
  1313.         sprintf(buf, "xshogi version %s, patchlevel %s based on xboard version %s", 
  1314.                   version, patchlevel, XBOARD_VERSION);
  1315.  
  1316.     /*
  1317.      * If there is to be a machine match, set it up.
  1318.      */
  1319.     if (matchMode != MatchFalse){
  1320.         if (appData.noChessProgram) {
  1321.             fprintf(stderr,
  1322.               "%s: can't have a match with no chess programs!\n",
  1323.               programName);
  1324.             exit(1);
  1325.         }
  1326.         DisplayMessage(buf);
  1327.         TwoMachinesPlayProc();
  1328.     }
  1329.     else {
  1330.         ResetProc();
  1331.         DisplayMessage(buf);
  1332.     }
  1333.  
  1334.     XtAppMainLoop(appContext);
  1335. }
  1336.  
  1337. void
  1338. CreateGCs()
  1339. {
  1340.     XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
  1341.         | GCBackground | GCFunction | GCPlaneMask;
  1342.     XGCValues gc_values;
  1343.     Font coordFontID;
  1344.  
  1345.     gc_values.plane_mask = AllPlanes;
  1346.     gc_values.line_width = LINE_GAP;
  1347.     gc_values.line_style = LineSolid;
  1348.     gc_values.function = GXcopy;
  1349.  
  1350.     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
  1351.     gc_values.background = XBlackPixel(xDisplay, xScreen);
  1352.     lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1353.  
  1354.     gc_values.background = XWhitePixel(xDisplay, xScreen);
  1355.     coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1356.     coordFontID = XLoadFont(xDisplay, appData.coordFont);
  1357.     coordFont = XQueryFont(xDisplay, coordFontID);
  1358.     XSetFont(xDisplay, coordGC, coordFontID);
  1359.  
  1360.     if (appData.monoMode) {
  1361.         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
  1362.         gc_values.background = XBlackPixel(xDisplay, xScreen);
  1363.         lightSquareGC = darkSquareGC = wbPieceGC
  1364.             = XtGetGC(shellWidget, value_mask, &gc_values);
  1365.         gc_values.foreground = XBlackPixel(xDisplay, xScreen);
  1366.         gc_values.background = XWhitePixel(xDisplay, xScreen);
  1367.         bwPieceGC
  1368.             = XtGetGC(shellWidget, value_mask, &gc_values);
  1369.     } else {
  1370.         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
  1371.         gc_values.background = XBlackPixel(xDisplay, xScreen);
  1372.         wbPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1373.  
  1374.         gc_values.foreground = XBlackPixel(xDisplay, xScreen);
  1375.         gc_values.background = XWhitePixel(xDisplay, xScreen);
  1376.         bwPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1377.  
  1378.         gc_values.foreground = appData.lightSquareColor;
  1379.         gc_values.background = appData.darkSquareColor;
  1380.         lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1381.  
  1382.         gc_values.foreground = appData.darkSquareColor;
  1383.         gc_values.background = appData.lightSquareColor;
  1384.         darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1385.  
  1386.         gc_values.foreground = appData.blackPieceColor;
  1387.         gc_values.background = appData.darkSquareColor;
  1388.         wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1389.  
  1390.         gc_values.foreground = appData.blackPieceColor;
  1391.         gc_values.background = appData.lightSquareColor;
  1392.         wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1393.  
  1394.         gc_values.foreground = appData.whitePieceColor;
  1395.         gc_values.background = appData.darkSquareColor;
  1396.         bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1397.  
  1398.         gc_values.foreground = appData.whitePieceColor;
  1399.         gc_values.background = appData.lightSquareColor;
  1400.         blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1401.  
  1402.         gc_values.function = (black_pixel_is_zero ? GXand : GXor);
  1403.  
  1404.         gc_values.foreground = XBlackPixel(xDisplay, xScreen);
  1405.         gc_values.background = XWhitePixel(xDisplay, xScreen);
  1406.         charPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1407.  
  1408.     }
  1409. }                
  1410.  
  1411.  
  1412. void
  1413. CreatePieces()
  1414. {
  1415.     XSynchronize(xDisplay, True);    /* Work-around for xlib/xt
  1416.                        buffering bug */
  1417.         
  1418. #ifdef WESTERN_BITMAPS
  1419.  
  1420.        ReadBitmap(appData.reverseBigSolidBitmap, &reverseBigSolidBitmap,
  1421.            NULL,
  1422.            bigsolidR_bits, bigsolidR_bits, bigsolidR_bits);
  1423.     ReadBitmap(appData.reverseSmallSolidBitmap, &reverseSmallSolidBitmap,
  1424.            NULL,
  1425.            smallsolidR_bits, smallsolidR_bits, smallsolidR_bits);
  1426.  
  1427.     ReadBitmap(appData.normalBigSolidBitmap, &normalBigSolidBitmap,
  1428.            NULL,
  1429.            bigsolid_bits, bigsolid_bits, bigsolid_bits);
  1430.     ReadBitmap(appData.normalSmallSolidBitmap, &normalSmallSolidBitmap,
  1431.            NULL,
  1432.            smallsolid_bits, smallsolid_bits, smallsolid_bits);
  1433.  
  1434.     ReadBitmap(appData.reversePawnBitmap, &reversePawnBitmap,
  1435.            &reverseSmallSolidBitmap,
  1436.            pawnR_bits, pawnR_bits, pawnR_bits);
  1437.     ReadBitmap(appData.reverseLanceBitmap, &reverseLanceBitmap,
  1438.            &reverseSmallSolidBitmap,
  1439.            lanceR_bits, lanceR_bits, lanceR_bits);
  1440.     ReadBitmap(appData.reverseKnightBitmap, &reverseKnightBitmap,
  1441.            &reverseSmallSolidBitmap,
  1442.            knightR_bits, knightR_bits, knightR_bits);
  1443.     ReadBitmap(appData.reverseSilverBitmap, &reverseSilverBitmap,
  1444.            &reverseBigSolidBitmap,
  1445.            silverR_bits, silverR_bits, silverR_bits);
  1446.     ReadBitmap(appData.reverseGoldBitmap, &reverseGoldBitmap,
  1447.            &reverseBigSolidBitmap,
  1448.            goldR_bits, goldR_bits, goldR_bits);
  1449.     ReadBitmap(appData.reverseRookBitmap, &reverseRookBitmap,
  1450.            &reverseBigSolidBitmap,
  1451.            rookR_bits, rookR_bits, rookR_bits);
  1452.     ReadBitmap(appData.reverseBishopBitmap, &reverseBishopBitmap,
  1453.            &reverseBigSolidBitmap,
  1454.            bishopR_bits, bishopR_bits, bishopR_bits);
  1455.     ReadBitmap(appData.reversePPawnBitmap, &reversePPawnBitmap,
  1456.            &reverseSmallSolidBitmap,
  1457.            pawnPR_bits, pawnPR_bits, pawnPR_bits);
  1458.     ReadBitmap(appData.reversePLanceBitmap, &reversePLanceBitmap,
  1459.            &reverseSmallSolidBitmap,
  1460.            lancePR_bits, lancePR_bits, lancePR_bits);
  1461.     ReadBitmap(appData.reversePKnightBitmap, &reversePKnightBitmap,
  1462.            &reverseSmallSolidBitmap,
  1463.            knightPR_bits, knightPR_bits, knightPR_bits);
  1464.     ReadBitmap(appData.reversePSilverBitmap, &reversePSilverBitmap,
  1465.            &reverseBigSolidBitmap,
  1466.            silverPR_bits, silverPR_bits, silverPR_bits);
  1467.     ReadBitmap(appData.reversePRookBitmap, &reversePRookBitmap,
  1468.            &reverseBigSolidBitmap,
  1469.            rookPR_bits, rookPR_bits, rookPR_bits);
  1470.     ReadBitmap(appData.reversePBishopBitmap, &reversePBishopBitmap,
  1471.            &reverseBigSolidBitmap,
  1472.            bishopPR_bits, bishopPR_bits, bishopPR_bits);
  1473.     ReadBitmap(appData.reverseKingBitmap, &reverseKingBitmap,
  1474.            &reverseBigSolidBitmap,
  1475.            kingR_bits, kingR_bits, kingR_bits);
  1476.  
  1477.     ReadBitmap(appData.normalPawnBitmap, &normalPawnBitmap,
  1478.            &normalSmallSolidBitmap,
  1479.            pawn_bits, pawn_bits, pawn_bits);
  1480.     ReadBitmap(appData.normalLanceBitmap, &normalLanceBitmap,
  1481.            &normalSmallSolidBitmap,
  1482.            lance_bits, lance_bits, lance_bits);
  1483.     ReadBitmap(appData.normalKnightBitmap, &normalKnightBitmap,
  1484.            &normalSmallSolidBitmap,
  1485.            knight_bits, knight_bits, knight_bits);
  1486.     ReadBitmap(appData.normalSilverBitmap, &normalSilverBitmap,
  1487.            &normalBigSolidBitmap,
  1488.            silver_bits, silver_bits, silver_bits);
  1489.     ReadBitmap(appData.normalGoldBitmap, &normalGoldBitmap,
  1490.            &normalBigSolidBitmap,
  1491.            gold_bits, gold_bits, gold_bits);
  1492.     ReadBitmap(appData.normalRookBitmap, &normalRookBitmap,
  1493.            &normalBigSolidBitmap,
  1494.            rook_bits, rook_bits, rook_bits);
  1495.     ReadBitmap(appData.normalBishopBitmap, &normalBishopBitmap,
  1496.            &normalBigSolidBitmap,
  1497.            bishop_bits, bishop_bits, bishop_bits);
  1498.     ReadBitmap(appData.normalPPawnBitmap, &normalPPawnBitmap,
  1499.            &normalSmallSolidBitmap,
  1500.            pawnP_bits, pawnP_bits, pawnP_bits);
  1501.     ReadBitmap(appData.normalPLanceBitmap, &normalPLanceBitmap,
  1502.            &normalSmallSolidBitmap,
  1503.            lanceP_bits, lanceP_bits, lanceP_bits);
  1504.     ReadBitmap(appData.normalPKnightBitmap, &normalPKnightBitmap,
  1505.            &normalSmallSolidBitmap,
  1506.            knightP_bits, knightP_bits, knightP_bits);
  1507.     ReadBitmap(appData.normalPSilverBitmap, &normalPSilverBitmap,
  1508.            &normalBigSolidBitmap,
  1509.            silverP_bits, silverP_bits, silverP_bits);
  1510.     ReadBitmap(appData.normalPRookBitmap, &normalPRookBitmap,
  1511.            &normalBigSolidBitmap,
  1512.            rookP_bits, rookP_bits, rookP_bits);
  1513.     ReadBitmap(appData.normalPBishopBitmap, &normalPBishopBitmap,
  1514.            &normalBigSolidBitmap,
  1515.            bishopP_bits, bishopP_bits, bishopP_bits);
  1516.     ReadBitmap(appData.normalKingBitmap, &normalKingBitmap,
  1517.            &normalBigSolidBitmap,
  1518.            king_bits, king_bits, king_bits);
  1519.  
  1520. #else
  1521.                                      
  1522.        ReadBitmap(appData.reverseBigSolidBitmap, &reverseBigSolidBitmap,
  1523.            NULL,
  1524.            bigsolidR_bits, bigsolidR_m_bits, bigsolidR_l_bits);
  1525.     ReadBitmap(appData.reverseSmallSolidBitmap, &reverseSmallSolidBitmap,
  1526.            NULL,
  1527.            smallsolidR_bits, smallsolidR_m_bits, smallsolidR_l_bits);
  1528.  
  1529.     ReadBitmap(appData.normalBigSolidBitmap, &normalBigSolidBitmap,
  1530.            NULL,
  1531.            bigsolid_bits, bigsolid_m_bits, bigsolid_l_bits);
  1532.     ReadBitmap(appData.normalSmallSolidBitmap, &normalSmallSolidBitmap,
  1533.            NULL,
  1534.            smallsolid_bits, smallsolid_m_bits, smallsolid_l_bits);
  1535.  
  1536.     ReadBitmap(appData.reversePawnBitmap, &reversePawnBitmap,
  1537.            &reverseSmallSolidBitmap,
  1538.            pawnR_bits, pawnR_m_bits, pawnR_l_bits);
  1539.     ReadBitmap(appData.reverseLanceBitmap, &reverseLanceBitmap,
  1540.            &reverseSmallSolidBitmap,
  1541.            lanceR_bits, lanceR_m_bits, lanceR_l_bits);
  1542.     ReadBitmap(appData.reverseKnightBitmap, &reverseKnightBitmap,
  1543.            &reverseSmallSolidBitmap,
  1544.            knightR_bits, knightR_m_bits, knightR_l_bits);
  1545.     ReadBitmap(appData.reverseSilverBitmap, &reverseSilverBitmap,
  1546.            &reverseBigSolidBitmap,
  1547.            silverR_bits, silverR_m_bits, silverR_l_bits);
  1548.     ReadBitmap(appData.reverseGoldBitmap, &reverseGoldBitmap,
  1549.            &reverseBigSolidBitmap,
  1550.            goldR_bits, goldR_m_bits, goldR_l_bits);
  1551.     ReadBitmap(appData.reverseRookBitmap, &reverseRookBitmap,
  1552.            &reverseBigSolidBitmap,
  1553.            rookR_bits, rookR_m_bits, rookR_l_bits);
  1554.     ReadBitmap(appData.reverseBishopBitmap, &reverseBishopBitmap,
  1555.            &reverseBigSolidBitmap,
  1556.            bishopR_bits, bishopR_m_bits, bishopR_l_bits);
  1557.     ReadBitmap(appData.reversePPawnBitmap, &reversePPawnBitmap,
  1558.            &reverseSmallSolidBitmap,
  1559.            pawnPR_bits, pawnPR_m_bits, pawnPR_l_bits);
  1560.     ReadBitmap(appData.reversePLanceBitmap, &reversePLanceBitmap,
  1561.            &reverseSmallSolidBitmap,
  1562.            lancePR_bits, lancePR_m_bits, lancePR_l_bits);
  1563.     ReadBitmap(appData.reversePKnightBitmap, &reversePKnightBitmap,
  1564.            &reverseSmallSolidBitmap,
  1565.            knightPR_bits, knightPR_m_bits, knightPR_l_bits);
  1566.     ReadBitmap(appData.reversePSilverBitmap, &reversePSilverBitmap,
  1567.            &reverseBigSolidBitmap,
  1568.            silverPR_bits, silverPR_m_bits, silverPR_l_bits);
  1569.     ReadBitmap(appData.reversePRookBitmap, &reversePRookBitmap,
  1570.            &reverseBigSolidBitmap,
  1571.            rookPR_bits, rookPR_m_bits, rookPR_l_bits);
  1572.     ReadBitmap(appData.reversePBishopBitmap, &reversePBishopBitmap,
  1573.            &reverseBigSolidBitmap,
  1574.            bishopPR_bits, bishopPR_m_bits, bishopPR_l_bits);
  1575.     ReadBitmap(appData.reverseKingBitmap, &reverseKingBitmap,
  1576.            &reverseBigSolidBitmap,
  1577.            kingR_bits, kingR_m_bits, kingR_l_bits);
  1578.  
  1579.     ReadBitmap(appData.normalPawnBitmap, &normalPawnBitmap,
  1580.            &normalSmallSolidBitmap,
  1581.            pawn_bits, pawn_m_bits, pawn_l_bits);
  1582.     ReadBitmap(appData.normalLanceBitmap, &normalLanceBitmap,
  1583.            &normalSmallSolidBitmap,
  1584.            lance_bits, lance_m_bits, lance_l_bits);
  1585.     ReadBitmap(appData.normalKnightBitmap, &normalKnightBitmap,
  1586.            &normalSmallSolidBitmap,
  1587.            knight_bits, knight_m_bits, knight_l_bits);
  1588.     ReadBitmap(appData.normalSilverBitmap, &normalSilverBitmap,
  1589.            &normalBigSolidBitmap,
  1590.            silver_bits, silver_m_bits, silver_l_bits);
  1591.     ReadBitmap(appData.normalGoldBitmap, &normalGoldBitmap,
  1592.            &normalBigSolidBitmap,
  1593.            gold_bits, gold_m_bits, gold_l_bits);
  1594.     ReadBitmap(appData.normalRookBitmap, &normalRookBitmap,
  1595.            &normalBigSolidBitmap,
  1596.            rook_bits, rook_m_bits, rook_l_bits);
  1597.     ReadBitmap(appData.normalBishopBitmap, &normalBishopBitmap,
  1598.            &normalBigSolidBitmap,
  1599.            bishop_bits, bishop_m_bits, bishop_l_bits);
  1600.     ReadBitmap(appData.normalPPawnBitmap, &normalPPawnBitmap,
  1601.            &normalSmallSolidBitmap,
  1602.            pawnP_bits, pawnP_m_bits, pawnP_l_bits);
  1603.     ReadBitmap(appData.normalPLanceBitmap, &normalPLanceBitmap,
  1604.            &normalSmallSolidBitmap,
  1605.            lanceP_bits, lanceP_m_bits, lanceP_l_bits);
  1606.     ReadBitmap(appData.normalPKnightBitmap, &normalPKnightBitmap,
  1607.            &normalSmallSolidBitmap,
  1608.            knightP_bits, knightP_m_bits, knightP_l_bits);
  1609.     ReadBitmap(appData.normalPSilverBitmap, &normalPSilverBitmap,
  1610.            &normalBigSolidBitmap,
  1611.            silverP_bits, silverP_m_bits, silverP_l_bits);
  1612.     ReadBitmap(appData.normalPRookBitmap, &normalPRookBitmap,
  1613.            &normalBigSolidBitmap,
  1614.            rookP_bits, rookP_m_bits, rookP_l_bits);
  1615.     ReadBitmap(appData.normalPBishopBitmap, &normalPBishopBitmap,
  1616.            &normalBigSolidBitmap,
  1617.            bishopP_bits, bishopP_m_bits, bishopP_l_bits);
  1618.     ReadBitmap(appData.normalKingBitmap, &normalKingBitmap,
  1619.            &normalBigSolidBitmap,
  1620.            king_bits, king_m_bits, king_l_bits);
  1621.  
  1622. #endif
  1623.  
  1624.     XSynchronize(xDisplay, False);    /* Work-around for xlib/xt
  1625.                        buffering bug */
  1626. }           
  1627.         
  1628.  
  1629.                     
  1630. int 
  1631. ReadBitmapFile(display, d, filename, width_return,
  1632.      height_return, bitmap_return,
  1633.      x_hot_return, y_hot_return)
  1634.          Display *display;
  1635.          Drawable d;
  1636.          char *filename;
  1637.          unsigned int *width_return, *height_return;
  1638.          Pixmap *bitmap_return;
  1639.          int *x_hot_return, *y_hot_return;
  1640.   int n;                
  1641.   if ((n = XReadBitmapFile(display, d, filename,
  1642.         width_return, height_return, bitmap_return, x_hot_return, y_hot_return)) 
  1643.               != BitmapSuccess)
  1644.     return(n);
  1645.   else
  1646.     { 
  1647.       /* transform a 1 plane pixmap to a k plane pixmap */
  1648.       return(BitmapSuccess);
  1649.     }
  1650. }
  1651.  
  1652.  
  1653. void
  1654. ReadBitmap(name, pm, qm, small_bits, medium_bits, large_bits)
  1655.     String name;
  1656.     Pixmap *pm, *qm;
  1657.     char small_bits[], medium_bits[], large_bits[];
  1658. {
  1659.     int x_hot, y_hot;
  1660.     u_int w, h;    
  1661.  
  1662.     if (name == NULL || ReadBitmapFile(xDisplay, xBoardWindow, name,
  1663.         &w, &h, pm, &x_hot, &y_hot) != BitmapSuccess
  1664.         || w != squareSize || h != squareSize) {
  1665.         unsigned long fg, bg;
  1666.         unsigned int depth;
  1667.         depth = DisplayPlanes(xDisplay, xScreen);
  1668.         if ( appData.monoMode ) {
  1669.           fg = XBlackPixel(xDisplay, xScreen);
  1670.           bg = XWhitePixel(xDisplay, xScreen);
  1671.         } else if ( qm == NULL ) {
  1672.           fg = appData.whitePieceColor;
  1673.           bg = appData.lightSquareColor;
  1674.         } else {
  1675.           fg = (black_pixel_is_zero ? 0 : ~0);
  1676.           bg = (black_pixel_is_zero ? ~0 : 0);
  1677.         };
  1678.         switch (boardSize) {
  1679.               case Large:
  1680.             *pm = XCreatePixmapFromBitmapData(xDisplay, xBoardWindow,
  1681.                   large_bits, squareSize, squareSize,
  1682.                   fg, bg, depth);
  1683.             break;
  1684.               case Medium:
  1685.             *pm = XCreatePixmapFromBitmapData(xDisplay, xBoardWindow,
  1686.                   medium_bits, squareSize, squareSize,
  1687.                   fg, bg, depth);
  1688.             break;
  1689.               case Small:
  1690.             *pm = XCreatePixmapFromBitmapData(xDisplay, xBoardWindow,
  1691.                   small_bits, squareSize, squareSize,
  1692.                   fg, bg, depth);
  1693.             break;
  1694.         }
  1695.     }     
  1696. }                  
  1697.  
  1698.  
  1699.  
  1700. void
  1701. CreateGrid()
  1702. {
  1703.     int i, offset;
  1704.  
  1705.     offset = 2 * (squareSize + LINE_GAP);
  1706.  
  1707.     for (i = 0; i < BOARD_SIZE + 1; i++) {
  1708.         gridSegments[i].x1 = offset;
  1709.                 gridSegments[i + BOARD_SIZE + 1].y1 = 0;
  1710.         gridSegments[i].y1 = gridSegments[i].y2
  1711.             = LINE_GAP / 2 + (i * (squareSize + LINE_GAP));
  1712.         gridSegments[i].x2 = LINE_GAP + BOARD_SIZE *
  1713.                 (squareSize + LINE_GAP) + offset;
  1714.         gridSegments[i + BOARD_SIZE + 1].x1 =
  1715.         gridSegments[i + BOARD_SIZE + 1].x2 = LINE_GAP / 2
  1716.             + (i * (squareSize + LINE_GAP)) + offset;
  1717.         gridSegments[i + BOARD_SIZE + 1].y2 =
  1718.             BOARD_SIZE * (squareSize + LINE_GAP);
  1719.     }
  1720. }               
  1721.  
  1722.  
  1723.  
  1724. void
  1725. CreatePieceMenus()
  1726. {
  1727.     int i;
  1728.     Widget entry;
  1729.     Arg args[1];
  1730.     ChessSquare selection;
  1731.     
  1732.     XtSetArg(args[0], XtNlabel, "Black");
  1733.     blackPieceMenu = XtCreatePopupShell("menuW", simpleMenuWidgetClass,
  1734.                        boardWidget, args, 1);
  1735.     for (i = 0; i < PIECE_MENU_SIZE; i++) {
  1736.         String item = pieceMenuStrings[i];
  1737.  
  1738.         if (strcmp(item, "----") == 0) {
  1739.             entry = XtCreateManagedWidget(item, smeLineObjectClass,
  1740.                               blackPieceMenu, NULL, 0);
  1741.         } else {
  1742.             entry = XtCreateManagedWidget(item, smeBSBObjectClass,
  1743.                               blackPieceMenu, NULL, 0);
  1744.             selection = pieceMenuTranslation[0][i];
  1745.             XtAddCallback(entry, XtNcallback,
  1746.                       (XtCallbackProc) PieceMenuSelect,
  1747.                       (caddr_t) selection);
  1748.             if (selection == BlackPawn) {
  1749.                 XtSetArg(args[0], XtNpopupOnEntry, entry);
  1750.                 XtSetValues(blackPieceMenu, args, 1);
  1751.             }
  1752.         }
  1753.     }
  1754.  
  1755.     XtSetArg(args[0], XtNlabel, "White");
  1756.     whitePieceMenu = XtCreatePopupShell("menuB", simpleMenuWidgetClass,
  1757.                        boardWidget, args, 1);
  1758.     for (i = 0; i < PIECE_MENU_SIZE; i++) {
  1759.         String item = pieceMenuStrings[i];
  1760.  
  1761.         if (strcmp(item, "----") == 0) {
  1762.             entry = XtCreateManagedWidget(item, smeLineObjectClass,
  1763.                               whitePieceMenu, NULL, 0);
  1764.         } else {
  1765.             entry = XtCreateManagedWidget(item, smeBSBObjectClass,
  1766.                               whitePieceMenu, NULL, 0);
  1767.             selection = pieceMenuTranslation[1][i];
  1768.             XtAddCallback(entry, XtNcallback,
  1769.                       (XtCallbackProc) PieceMenuSelect,
  1770.                       (caddr_t) selection);
  1771.             if (selection == WhitePawn) {
  1772.                 XtSetArg(args[0], XtNpopupOnEntry, entry);
  1773.                 XtSetValues(whitePieceMenu, args, 1);
  1774.             }
  1775.         }
  1776.     }
  1777.  
  1778.     XtRegisterGrabAction(PieceMenuPopup, True,
  1779.                  (unsigned)(ButtonPressMask|ButtonReleaseMask),
  1780.                  GrabModeAsync, GrabModeAsync);
  1781. }    
  1782.  
  1783. void
  1784. PieceMenuPopup(w, event, params, num_params)
  1785.     Widget w;
  1786.     XEvent *event;
  1787.         String *params;
  1788.         Cardinal *num_params;
  1789. {
  1790.     if (event->type != ButtonPress) return;
  1791.     if (gameMode != EditPosition) return;
  1792.     if (((pmFromX = EventToXSquare(event->xbutton.x)) < 1) ||
  1793.        (pmFromX > BOARD_SIZE+2) ||
  1794.         ((pmFromY = EventToSquare(event->xbutton.y)) < 0)) {
  1795.         pmFromX = pmFromY = -1;
  1796.         return;
  1797.     }
  1798.     if (flipView)
  1799.       pmFromX = BOARD_SIZE + 3 - pmFromX;
  1800.     else
  1801.       pmFromY = BOARD_SIZE - 1 - pmFromY;
  1802.  
  1803.     XtPopupSpringLoaded(XtNameToWidget(boardWidget, params[0]));
  1804. }
  1805.  
  1806. static void
  1807. PieceMenuSelect(w, piece, junk)
  1808.      Widget w;
  1809.      ChessSquare piece;
  1810.      caddr_t junk;
  1811. {
  1812.     if (pmFromX < 0 || pmFromY < 0) return;
  1813.     if (off_board(pmFromX) ) {
  1814.       int i, c;
  1815.       switch (piece) {
  1816.         case ClearBoard:
  1817.               break;
  1818.         case BlackPlay:
  1819.               break;
  1820.         case WhitePlay:
  1821.               break;
  1822.             default: 
  1823.                i = pieceToCatchedIndex[piece];
  1824.         c = (piece >= WhitePawn );
  1825.         catches[0][c][i]++;
  1826.         UpdateCatched(c, i, True, False, 0);
  1827.         XSync(xDisplay, False);
  1828.         return;
  1829.           }
  1830.     }
  1831.     pmFromX -= 2;
  1832.     switch (piece) {
  1833.           case ClearBoard:
  1834.         for (pmFromY = 0; pmFromY < BOARD_SIZE; pmFromY++)
  1835.           for (pmFromX = 0; pmFromX < BOARD_SIZE; pmFromX++) {
  1836.               boards[0][pmFromY][pmFromX] = EmptySquare;
  1837.               DrawSquare(pmFromY, pmFromX, EmptySquare);
  1838.           }
  1839.         ClearCatches(catches[0]);
  1840.         UpdateCatched(0,0,False,True, 0);
  1841.         UpdateCatched(1,0,False,True, 0);
  1842.         break;
  1843.  
  1844.           case BlackPlay:  /*not currently on menu*/
  1845.         SetBlackToPlay();
  1846.         break;
  1847.  
  1848.           case WhitePlay:  /*not currently on menu*/
  1849.         SetWhiteToPlay();
  1850.         break;
  1851.  
  1852.           default:
  1853.         boards[0][pmFromY][pmFromX] = piece;
  1854.         DrawSquare(pmFromY, pmFromX, piece);
  1855.         break;
  1856.     }
  1857.     XSync(xDisplay, False);
  1858. }
  1859.  
  1860. static void
  1861. SetBlackToPlay()
  1862. {
  1863.     int saveCM;
  1864.  
  1865.     if (gameMode != EditPosition) return;
  1866.     whitePlaysFirst = False;
  1867.     saveCM = currentMove;
  1868.     currentMove = 0;  /*kludge*/
  1869.     DisplayClocks(ReDisplayTimers);
  1870.     currentMove = saveCM;
  1871. }
  1872.  
  1873. static void
  1874. SetWhiteToPlay()
  1875. {
  1876.     int saveCM;
  1877.  
  1878.     if (gameMode != EditPosition) return;
  1879.     whitePlaysFirst = True;
  1880.     saveCM = currentMove;
  1881.     currentMove = 1;  /*kludge*/
  1882.     DisplayClocks(ReDisplayTimers);
  1883.     currentMove = saveCM;
  1884. }
  1885.  
  1886. /*
  1887.  * If the user selects on a border boundary or off the board, return failure.
  1888.  * Otherwise map the event coordinate to the square.
  1889.  */
  1890. int
  1891. EventToSquare(x)
  1892.     int x;
  1893. {
  1894.     if (x < LINE_GAP)
  1895.         return -1;
  1896.     x -= LINE_GAP;
  1897.     if ((x % (squareSize + LINE_GAP)) >= squareSize)
  1898.         return -1;
  1899.     x /= (squareSize + LINE_GAP);
  1900.     if (x >= BOARD_SIZE)
  1901.         return -1;
  1902.     return x;
  1903. }
  1904.  
  1905.  
  1906.  
  1907. int
  1908. EventToXSquare(x)
  1909.     int x;
  1910. {
  1911.     if (x < LINE_GAP)
  1912.         return -1;
  1913.     x -= LINE_GAP;
  1914.     if ((x % (squareSize + LINE_GAP)) >= squareSize)
  1915.         return -1;
  1916.     x /= (squareSize + LINE_GAP);
  1917.     if (x >= BOARD_SIZE+4)
  1918.         return -1;
  1919.     return x;
  1920. }
  1921.  
  1922.  
  1923.  
  1924. ChessSquare
  1925. CharToPiece(c, p)
  1926.     int c;
  1927.     int p;
  1928. {               
  1929.     if ( p )
  1930.         switch (c) {
  1931.         default:
  1932.         case '.':    return EmptySquare;
  1933.         case 'P':    return BlackPPawn;
  1934.         case 'L':    return BlackPLance;
  1935.         case 'N':    return BlackPKnight;
  1936.         case 'S':    return BlackPSilver;
  1937.         case 'G':    return BlackGold;
  1938.         case 'R':    return BlackPRook;
  1939.         case 'B':    return BlackPBishop;
  1940.         case 'K':    return BlackKing;
  1941.         case 'p':    return WhitePPawn;
  1942.         case 'l':    return WhitePLance;
  1943.         case 'n':    return WhitePKnight;
  1944.         case 's':    return WhitePSilver;
  1945.         case 'g':    return WhiteGold;
  1946.         case 'r':    return WhitePRook;
  1947.         case 'b':    return WhitePBishop;
  1948.         case 'k':    return WhiteKing;
  1949.         }
  1950.     else
  1951.         switch (c) {
  1952.         default:
  1953.         case '.':    return EmptySquare;
  1954.         case 'P':    return BlackPawn;
  1955.         case 'L':    return BlackLance;
  1956.         case 'N':    return BlackKnight;
  1957.         case 'S':    return BlackSilver;
  1958.         case 'G':    return BlackGold;
  1959.         case 'R':    return BlackRook;
  1960.         case 'B':    return BlackBishop;
  1961.         case 'K':    return BlackKing;
  1962.         case 'p':    return WhitePawn;
  1963.         case 'l':    return WhiteLance;
  1964.         case 'n':    return WhiteKnight;
  1965.         case 's':    return WhiteSilver;
  1966.         case 'g':    return WhiteGold;
  1967.         case 'r':    return WhiteRook;
  1968.         case 'b':    return WhiteBishop;
  1969.         case 'k':    return WhiteKing;
  1970.         }                              
  1971.  
  1972. }
  1973.  
  1974.  
  1975. /* Convert coordinates to normal algebraic notation.
  1976.    promoPiece must be '\000' if not a promotion.
  1977. */
  1978. ChessMove
  1979. MakeAlg(fromX, fromY, toX, toY, promoPiece, currentBoardIndex, out)
  1980.      int fromX, fromY, toX, toY;
  1981.      char promoPiece;
  1982.      int currentBoardIndex;
  1983.      char out[MOVE_LEN];
  1984. {
  1985.     ChessSquare piece;
  1986.     ChessMove ret;
  1987.     char *outp = out;
  1988.     int i;
  1989.  
  1990.         if ( fromX > 80 ) {
  1991.         ChessSquare piece;
  1992.         piece = (fromX - 81);
  1993.                 *outp++ = catchedIndexToChar[piece];
  1994.                 *outp++ = '*';
  1995.         *outp++ = '9' - toX;
  1996.         *outp++ = 'i' - toY;
  1997.         *outp++ = '\000';
  1998.                 return (BLACK_ON_MOVE ? BlackDrop : WhiteDrop);
  1999.     } else {
  2000.         *outp++ = '9' - fromX;
  2001.         *outp++ = 'i' - fromY;
  2002.         *outp++ = '9' - toX;
  2003.         *outp++ = 'i' - toY;
  2004.         *outp++ = promoPiece;
  2005.         *outp++ = '\000';
  2006.                 if ( promoPiece == '\000' )
  2007.                    return NormalMove;
  2008.         else
  2009.            return (BLACK_ON_MOVE ? BlackPromotion : WhitePromotion);
  2010.     }
  2011.  
  2012. }
  2013.  
  2014. void
  2015. DrawSquare(row, column, piece)
  2016.     int row, column;
  2017.     ChessSquare piece;
  2018. {
  2019.     int square_color, x, y, direction, font_ascent, font_descent;
  2020.     char string[2];
  2021.     XCharStruct overall;
  2022.  
  2023.         int offset;
  2024.  
  2025.     offset = 2 * (squareSize + LINE_GAP);
  2026.  
  2027.     if (flipView) {
  2028.         x = LINE_GAP + ((BOARD_SIZE-1)-column) * 
  2029.             (squareSize + LINE_GAP) + offset;
  2030.         y = LINE_GAP + row * (squareSize + LINE_GAP);
  2031.     } else {
  2032.         x = LINE_GAP + column * (squareSize + LINE_GAP) + offset;
  2033.         y = LINE_GAP + ((BOARD_SIZE-1)-row) * 
  2034.             (squareSize + LINE_GAP);
  2035.     }
  2036.  
  2037.     square_color = ((column + row) % 2) == 1;
  2038.  
  2039.     if (piece == EmptySquare) {
  2040.         if ( column < 0 || column >= BOARD_SIZE )
  2041.           XFillRectangle(xDisplay, xBoardWindow,
  2042.                      wbPieceGC,
  2043.                      x, y, squareSize, squareSize);
  2044.         else
  2045.           XFillRectangle(xDisplay, xBoardWindow,
  2046.                      square_color ? lightSquareGC : darkSquareGC,
  2047.                      x, y, squareSize, squareSize);
  2048.     } else if (appData.monoMode || column < 0 || column >= BOARD_SIZE) {
  2049.         if (square_color)
  2050.           XCopyArea(xDisplay, ((int) piece < (int) WhitePawn) ^ flipView
  2051.                  ? *pieceToNormal[(int) piece]
  2052.                  : *pieceToReverse[(int) piece],
  2053.                  xBoardWindow, 
  2054.                  (appData.monoMode ? wbPieceGC : wlPieceGC), 
  2055.                  0, 0,
  2056.                  squareSize, squareSize, x, y);
  2057.         else
  2058.           XCopyArea(xDisplay, ((int) piece < (int) WhitePawn) ^ flipView
  2059.                  ? *pieceToNormal[(int) piece]
  2060.                  : *pieceToReverse[(int) piece],
  2061.                  xBoardWindow, 
  2062.                  (appData.monoMode ? bwPieceGC : wlPieceGC), 
  2063.                  0, 0,
  2064.                  squareSize, squareSize, x, y);
  2065.     } else {          
  2066.         if (square_color) {
  2067.           XCopyArea(xDisplay, ((int) piece < (int) WhitePawn) ^ flipView
  2068.                  ? *pieceToNormalSolid[(int) piece]
  2069.                  : *pieceToReverseSolid[(int) piece],
  2070.                  xBoardWindow, 
  2071.                  wlPieceGC, 
  2072.                  0, 0,
  2073.                  squareSize, squareSize, x, y);
  2074.           XCopyArea(xDisplay, ((int) piece < (int) WhitePawn) ^ flipView
  2075.                  ? *pieceToNormal[(int) piece]
  2076.                  : *pieceToReverse[(int) piece],
  2077.                  xBoardWindow, 
  2078.                  charPieceGC, 
  2079.                  0, 0,
  2080.                  squareSize, squareSize, x, y);
  2081.         } else {
  2082.           XCopyArea(xDisplay, ((int) piece < (int) WhitePawn) ^ flipView
  2083.                  ? *pieceToNormalSolid[(int) piece]
  2084.                  : *pieceToReverseSolid[(int) piece],
  2085.                  xBoardWindow, 
  2086.                  wlPieceGC, 
  2087.                  0, 0,
  2088.                  squareSize, squareSize, x, y);
  2089.           XCopyArea(xDisplay, ((int) piece < (int) WhitePawn) ^ flipView
  2090.                  ? *pieceToNormal[(int) piece]
  2091.                  : *pieceToReverse[(int) piece],
  2092.                  xBoardWindow, 
  2093.                  charPieceGC, 
  2094.                  0, 0,
  2095.                  squareSize, squareSize, x, y);
  2096.         }
  2097.     }
  2098.         string[1] = '\000';
  2099.     if (appData.showCoords && column >= 0 && column < 9 && row == (flipView ? 8 : 0)) {
  2100.         string[0] = '9' - column;
  2101.         XTextExtents(coordFont, string, 1, &direction, 
  2102.         &font_ascent, &font_descent, &overall);
  2103.         if (appData.monoMode) {
  2104.            XDrawImageString(xDisplay, xBoardWindow, coordGC,
  2105.             x + squareSize - overall.width - 2, 
  2106.             y + squareSize - font_descent - 1, string, 1);
  2107.         } else {
  2108.            XDrawString(xDisplay, xBoardWindow, coordGC,
  2109.             x + squareSize - overall.width - 2, 
  2110.             y + squareSize - font_descent - 1, string, 1);
  2111.         }
  2112.     }
  2113.     if (appData.showCoords && row >= 0 && row < 9 && column == (flipView ? 8 : 0)) {
  2114.         string[0] = 'i' - row;
  2115.         XTextExtents(coordFont, string, 1, &direction, 
  2116.         &font_ascent, &font_descent, &overall);
  2117.         if (appData.monoMode) {
  2118.            XDrawImageString(xDisplay, xBoardWindow, coordGC,
  2119.             x + 2, y + font_ascent + 1, string, 1);
  2120.         } else {
  2121.            XDrawString(xDisplay, xBoardWindow, coordGC,
  2122.             x + 2, y + font_ascent + 1, string, 1);
  2123.         }        
  2124.     }   
  2125. }
  2126.  
  2127. void
  2128. EventProc(widget, unused, event)
  2129.     Widget widget;
  2130.     caddr_t unused;
  2131.     XEvent *event;
  2132. {
  2133.     if (event->type == MappingNotify) {
  2134.         XRefreshKeyboardMapping((XMappingEvent *) event);
  2135.         return;
  2136.     }
  2137.  
  2138.     if (!XtIsRealized(widget))
  2139.         return;
  2140.  
  2141.     if ((event->type == ButtonPress) || (event->type == ButtonRelease))
  2142.         if (event->xbutton.button != Button1)
  2143.             return;
  2144.  
  2145.     switch (event->type) {
  2146.     case Expose:
  2147.         DrawPosition(widget, (XExposeEvent *) event);
  2148.         break;
  2149.     default:
  2150.         return;
  2151.     }
  2152. }
  2153.  
  2154. /*
  2155.  * event handler for redrawing the board
  2156.  */
  2157. void
  2158. DrawPosition(w, event)
  2159.     Widget w;
  2160.     XExposeEvent *event;
  2161. {
  2162.     Arg args[1];
  2163.     int i, j;
  2164.         if (!appData.Iconic){
  2165.         XtSetArg(args[0], XtNiconic, False);
  2166.         XtSetValues(shellWidget, args, 1);
  2167.         }
  2168.  
  2169.     /*
  2170.      * It would be simpler to clear the window with XClearWindow()
  2171.      * but this causes a very distracting flicker.
  2172.      */
  2173.     XDrawSegments(xDisplay, xBoardWindow, lineGC,
  2174.         gridSegments, (BOARD_SIZE + 1) * 2);
  2175.  
  2176.     for (i = 0; i < BOARD_SIZE; i++)
  2177.         for (j = 0; j < BOARD_SIZE; j++)
  2178.             DrawSquare(i, j, boards[currentMove][i][j]);
  2179.  
  2180.     UpdateCatched(0,0,False,True,currentMove);
  2181.     UpdateCatched(1,0,False,True,currentMove);
  2182.  
  2183.     XSync(xDisplay, False);
  2184. }
  2185.  
  2186. void
  2187. InitPosition()
  2188. {
  2189.     currentMove = forwardMostMove = 0;
  2190.     CopyBoard(boards[0], initialPosition);
  2191.         ClearCatches(catches[0]);
  2192.     
  2193.     DrawPosition(boardWidget, (XExposeEvent *) NULL);
  2194. }
  2195.  
  2196. void
  2197. CopyBoard(to, from)
  2198.     Board to, from;
  2199. {
  2200.     int i, j;
  2201.  
  2202.     for (i = 0; i < BOARD_SIZE; i++)
  2203.         for (j = 0; j < BOARD_SIZE; j++)
  2204.             to[i][j] = from[i][j];
  2205. }
  2206.         
  2207.  
  2208.  
  2209. void
  2210. CopyCatches(to, from)
  2211.     Catched to, from;
  2212. {
  2213.     int i, j;
  2214.  
  2215.     for (i = 0; i < 2; i++)
  2216.         for (j = 0; j < 8; j++)
  2217.             to[i][j] = from[i][j];
  2218. }
  2219.  
  2220.  
  2221.  
  2222.  
  2223. void
  2224. SendCurrentBoard(fp)
  2225.     FILE *fp;
  2226. {
  2227.     SendBoard(fp, boards[currentMove], catches[currentMove]);
  2228. }
  2229.  
  2230. void
  2231. SendBoard(fp, board, catches)
  2232.     FILE *fp;
  2233.         Board board;
  2234.     Catched catches;
  2235. {
  2236.     char message[MSG_SIZ];
  2237.     ChessSquare *bp;
  2238.     int i, j;
  2239.  
  2240.     SendToProgram("edit\n", fp);
  2241.     SendToProgram("#\n", fp);
  2242.     for (i = BOARD_SIZE - 1; i >= 0; i--) {
  2243.         bp = &board[i][0];
  2244.         for (j = 0; j < BOARD_SIZE; j++, bp++) {
  2245.             if ((int) *bp < (int) WhitePawn) {
  2246.                 sprintf(message, "%c%c%c\n",
  2247.                     pieceToChar[(int) *bp],
  2248.                     '9' - j, 'i' - i);
  2249.                 SendToProgram(message, fp);
  2250.             }
  2251.         }
  2252.     }
  2253.  
  2254.     for ( i = 0; i <= 7; i++ ) {
  2255.         int n;
  2256.         for ( n = catches[0][i]; n > 0; n-- ) {
  2257.             sprintf(message, "%c*\n",
  2258.                 catchedIndexToChar[i]);
  2259.                 SendToProgram(message, fp);
  2260.         };
  2261.     }
  2262.  
  2263.     SendToProgram("c\n", fp);
  2264.     for (i = BOARD_SIZE - 1; i >= 0; i--) {
  2265.         bp = &board[i][0];
  2266.         for (j = 0; j < BOARD_SIZE; j++, bp++) {
  2267.             if (((int) *bp != (int) EmptySquare)
  2268.                 && ((int) *bp >= (int) WhitePawn)) {
  2269.                 sprintf(message, "%c%c%c\n",
  2270.                     pieceToChar[(int) *bp -
  2271.                             (int) WhitePawn],
  2272.                     '9' - j, 'i' - i);
  2273.                 SendToProgram(message, fp);
  2274.             }
  2275.         }
  2276.     }
  2277.  
  2278.     for ( i = 0; i <= 7; i++ ) {
  2279.         int n;
  2280.         for ( n = catches[1][i]; n > 0; n-- ) {
  2281.             sprintf(message, "%c*\n",
  2282.                 catchedIndexToChar[i]);
  2283.                 SendToProgram(message, fp);
  2284.         };
  2285.     }
  2286.  
  2287.     SendToProgram(".\n", fp);
  2288. }
  2289.  
  2290.  
  2291.  
  2292.  
  2293.  
  2294.  
  2295. static
  2296. int
  2297. PromotionPossible (fromY, toY, piece)
  2298.     int fromY, toY;
  2299.     ChessSquare piece;
  2300.   if ( (int) piece < (int) WhitePawn ) {
  2301.     if ( fromY < 6 && toY < 6 ) return(False);
  2302.   } else {
  2303.     if ( fromY > 2 && toY > 2 ) return(False);
  2304.   };    
  2305.  
  2306.   return piecePromotable[(int) piece];
  2307.  
  2308. }
  2309.  
  2310.  
  2311. static
  2312. void
  2313. ShowCount (row, column, n)
  2314.    int row, column, n;
  2315. {
  2316.    int offset = 2 * (squareSize + LINE_GAP);
  2317.    int x, y, direction, font_ascent, font_descent;
  2318.    char string[2];
  2319.    XCharStruct overall;
  2320.  
  2321.    DrawSquare (row, column, EmptySquare);
  2322.    if ( n <= 1 ) {
  2323.      return;
  2324.    };
  2325.  
  2326.    if (flipView) {
  2327.           x = LINE_GAP + ((BOARD_SIZE-1)-column) *
  2328.               (squareSize + LINE_GAP) + offset;
  2329.           y = LINE_GAP + row * (squareSize + LINE_GAP);
  2330.    } else {
  2331.           x = LINE_GAP + column * (squareSize + LINE_GAP) + offset;
  2332.           y = LINE_GAP + ((BOARD_SIZE-1)-row) *
  2333.               (squareSize + LINE_GAP);
  2334.    }
  2335.  
  2336.    x -= squareSize / 2;
  2337.  
  2338.    string[1] = '\000';
  2339.  
  2340.    if ( n > 9 )
  2341.      string[0] = '*';
  2342.    else 
  2343.      string[0] = '0'+n;
  2344.  
  2345.    XTextExtents(coordFont, string, 1, &direction,
  2346.                 &font_ascent, &font_descent, &overall);
  2347.    if (appData.monoMode) {
  2348.       XDrawImageString(xDisplay, xBoardWindow, coordGC,
  2349.            x + squareSize - overall.width - 2,
  2350.            y + squareSize - font_descent - 1, string, 1);
  2351.    } else {
  2352.       XDrawString(xDisplay, xBoardWindow, coordGC,
  2353.            x + squareSize - overall.width - 2,
  2354.            y + squareSize - font_descent - 1, string, 1);
  2355.    }
  2356. }
  2357.  
  2358.  
  2359. void UpdateCatched (Color,Figure,Drop,DropAll,currentMove)
  2360.  
  2361. int Color,Figure,Drop,DropAll,currentMove;
  2362.  
  2363. {
  2364.  
  2365.   int n,F,C;
  2366.   int x,y;
  2367.  
  2368.   /* Determine first row and column. */
  2369.  
  2370.   if ( Color ) { 
  2371.     x = -1; y = BOARD_SIZE-1;
  2372.   } else {
  2373.     x = BOARD_SIZE; y = 0;
  2374.   }; 
  2375.  
  2376.  
  2377.   if ( DropAll )
  2378.     n = 0;
  2379.   else
  2380.     n = catches[currentMove][Color][Figure];
  2381.  
  2382.   /* Update the display for captured pieces
  2383.      if no piece of the dropped type is there (Drop && n==1)
  2384.      or if a piece type is removed (NOT Drop && n==0).
  2385.      In the other cases update only the count. */
  2386.  
  2387.   if ( DropAll || (Drop && (n==1)) || ((! Drop) && (n==0)) ) {
  2388.     /* show all captured pieces */
  2389.     n = 0;
  2390.     for ( F = pawn; F<=king; F++ ) {
  2391.       int c;
  2392.       if ( (c=catches[currentMove][Color][F])>0 ) {
  2393.         n++;
  2394.     DrawSquare(y, x, catchedIndexToPiece[Color][F]); 
  2395.         ShowCount(y, Color ? (x-1) : (x+1), c);
  2396.         if ( Color ) y--; else y++;
  2397.       };
  2398.     };
  2399.     if ( DropAll ) {
  2400.       for ( ; n < 9; n++ ) {
  2401.         DrawSquare(y, x, EmptySquare);
  2402.         ShowCount(y, Color ? (x-1) : (x+1), 0);
  2403.         if ( Color ) y--; else y++;
  2404.       }
  2405.     } else if ( ! Drop ) {
  2406.       /* remove one line ! */
  2407.       DrawSquare(y, x, EmptySquare);
  2408.       ShowCount(y, Color ? (x-1) : (x+1), 0);
  2409.     };
  2410.   } else {
  2411.     /* show the actual count */
  2412.     for ( F = pawn; F <= Figure-1; F++ ) {
  2413.       if ( catches[currentMove][Color][F] > 0 ) {
  2414.         if ( Color ) y--; else y++;
  2415.       };
  2416.     };
  2417.    ShowCount(y, Color ? (x-1) : (x+1), n); 
  2418.   };
  2419.  
  2420. };
  2421.  
  2422.  
  2423. static
  2424. int
  2425. PieceOfCatched (color, x, y, currentMove)
  2426.     int color, x, y, currentMove;
  2427. {
  2428.   int F, n;
  2429.  
  2430.   if ( color ) {
  2431.     if ( x != 1 ) return (no_piece);
  2432.     y = 8 - y;
  2433.   } else {
  2434.     if ( x != 11 ) return (no_piece);
  2435.   };
  2436.  
  2437.   for ( F = pawn, n = 0; F <= king; F++ ) {
  2438.     if ( catches[currentMove][color][F] > 0 ) {
  2439.     if ( n == y ) return (F);
  2440.     n++;
  2441.     };
  2442.   };
  2443.  
  2444.   return (no_piece);
  2445. }
  2446.  
  2447.  
  2448.  
  2449.  
  2450.  
  2451. /*
  2452.  * event handler for parsing user moves
  2453.  */
  2454. void
  2455. HandleUserMove(w, event)
  2456.     Widget w;
  2457.     XEvent *event;
  2458. {
  2459.     ChessMove move_type;
  2460.     ChessSquare from_piece;
  2461.     int to_x, to_y;
  2462.  
  2463.     if ((w != boardWidget) || (matchMode != MatchFalse))
  2464.         return;
  2465.  
  2466.     if (promotionUp) {
  2467.         XtPopdown(promotionShell);
  2468.         XtDestroyWidget(promotionShell);
  2469.         promotionUp = False;
  2470.         fromX = fromY = -1;
  2471.     }
  2472.  
  2473.     switch (gameMode) {
  2474.           case EndOfGame:
  2475.           case PlayFromGameFile:
  2476.           case TwoMachinesPlay:
  2477.         return;
  2478.           case MachinePlaysBlack:
  2479.         if (BLACK_ON_MOVE)
  2480.             return;
  2481.         break;
  2482.           case MachinePlaysWhite:
  2483.         if (!BLACK_ON_MOVE)
  2484.             return;
  2485.         break;
  2486.           default:
  2487.         break;
  2488.     }
  2489.  
  2490.     switch (event->type) {
  2491.           case ButtonPress:
  2492.         if ((fromX >= 0) || (fromY >= 0))
  2493.           return;
  2494.         if (((fromX = EventToXSquare(event->xbutton.x)) < 1) ||
  2495.                     (fromX > BOARD_SIZE+2) ||
  2496.             ((fromY = EventToSquare(event->xbutton.y)) < 0)) {
  2497.             fromX = fromY = -1;
  2498.             return;
  2499.         }
  2500.         if (flipView)
  2501.           fromX = BOARD_SIZE + 3 - fromX;
  2502.         else
  2503.           fromY = BOARD_SIZE - 1 - fromY;
  2504.         break;
  2505.  
  2506.           case ButtonRelease:
  2507.         if ((fromX < 0) || (fromY < 0)) return;
  2508.  
  2509.         if (((to_x = EventToXSquare(event->xbutton.x)) < 1)
  2510.                 || (to_x > BOARD_SIZE+2)
  2511.             || ((to_y = EventToSquare(event->xbutton.y)) < 0)) {
  2512.             if (gameMode == EditPosition)
  2513.             if ( !off_board(fromX) )
  2514.             { 
  2515.               fromX -= 2;
  2516.               boards[0][fromY][fromX] = EmptySquare;
  2517.               DrawSquare(fromY, fromX, EmptySquare);
  2518.               XSync(xDisplay, False);
  2519.             }
  2520.             fromX = fromY = -1;
  2521.             return;
  2522.         }
  2523.         if (flipView)
  2524.             to_x = BOARD_SIZE + 3 - to_x;
  2525.         else
  2526.             to_y = BOARD_SIZE - 1 - to_y;
  2527.  
  2528.         if ((fromX == to_x) && (fromY == to_y)) {
  2529.             fromX = fromY = -1;
  2530.             return;
  2531.         }
  2532.  
  2533.         if (gameMode == EditPosition) {
  2534.                   ChessSquare piece;
  2535.           if ( off_board(fromX) ) {
  2536.             /* Remove a catched piece */
  2537.             int c = ((fromX < 5) ^ flipView);
  2538.             int i = PieceOfCatched(c,fromX,fromY,0);
  2539.             if ( i == no_piece ) {
  2540.                 fromX = fromY = -1;
  2541.                  return;
  2542.             } else {
  2543.                 piece = catchedIndexToPiece[c][i];
  2544.                         catches[0][c][i]--;
  2545.                         UpdateCatched(c, i, False, False, 0);
  2546.             }
  2547.           } else {
  2548.             /* remove piece from board field */
  2549.             fromX -= 2;
  2550.             piece = boards[0][fromY][fromX];
  2551.             boards[0][fromY][fromX] = EmptySquare;
  2552.             DrawSquare(fromY, fromX, EmptySquare);
  2553.           }
  2554.           if ( !off_board(to_x) ) {
  2555.                 /* drop piece to board field */    
  2556.                         ChessSquare catched_piece;
  2557.                 to_x -= 2;
  2558.             catched_piece = boards[0][to_y][to_x];
  2559.                         if ( catched_piece != EmptySquare ) {
  2560.               /* put piece to catched pieces */
  2561.                             int i = pieceToCatchedIndex[catched_piece];
  2562.                             int c = (catched_piece < WhitePawn );
  2563.                             catches[0][c][i]++;
  2564.                             UpdateCatched(c, i, True, False, 0);
  2565.                         };
  2566.             /* place moved piece */
  2567.             boards[0][to_y][to_x] = piece;
  2568.             DrawSquare(to_y, to_x, piece);
  2569.           }
  2570.           fromX = fromY = -1;
  2571.           XSync(xDisplay, False);
  2572.           return;
  2573.         }
  2574.         
  2575.         if ( off_board(fromX) ) {
  2576.             int c = BLACK_ON_MOVE ? 0 : 1;
  2577.             int piece = PieceOfCatched(c,fromX,fromY,currentMove);
  2578.             if ( piece == no_piece ) {
  2579.                 fromX = fromY = -1;
  2580.                  return;
  2581.             } else {
  2582.                 fromX = fromY = piece + 81;
  2583.                 to_x -= 2;
  2584.                 move_type = BLACK_ON_MOVE ? BlackDrop : WhiteDrop;
  2585.                   MakeMove(&move_type, fromX, fromY, to_x, to_y);
  2586.                   FinishUserMove(move_type, to_x, to_y);
  2587.                   break;
  2588.             };
  2589.         } else if ( off_board(to_x) ) {
  2590.             fromX = fromY = -1;
  2591.             return;
  2592.                 } else {
  2593.           fromX -= 2; to_x -= 2;
  2594.           from_piece = boards[currentMove][fromY][fromX];
  2595.           if ( PromotionPossible(fromY, to_y, from_piece) ) {
  2596.               PromotionPopUp(from_piece, to_x, to_y);
  2597.             return;
  2598.           }
  2599.           move_type = NormalMove;
  2600.           MakeMove(&move_type, fromX, fromY, to_x, to_y);
  2601.           FinishUserMove(move_type, to_x, to_y);
  2602.           break;
  2603.         }
  2604.     }
  2605. }
  2606.  
  2607. void
  2608. FinishUserMove(move_type, to_x, to_y)
  2609.          ChessMove move_type;
  2610.          int to_x, to_y;
  2611. {
  2612.     char user_move[MSG_SIZ];
  2613.  
  2614.     switch (move_type) {
  2615.           default:
  2616.         fprintf(stderr, "%s: internal error; bad move_type\n",
  2617.             programName);
  2618.         break;
  2619.           case BlackPromotion:
  2620.           case WhitePromotion:
  2621.         sprintf(user_move, "%c%c%c%c+\n",
  2622.             '9' - fromX, 'i' - fromY, '9' - to_x, 'i' - to_y);
  2623.         break;
  2624.           case BlackDrop:
  2625.           case WhiteDrop:
  2626.         sprintf(user_move, "%c*%c%c\n",
  2627.             catchedIndexToChar[fromX - 81],'9' - to_x, 'i' - to_y);
  2628.         break;
  2629.           case NormalMove:
  2630.         sprintf(user_move, "%c%c%c%c\n",
  2631.             '9' - fromX, 'i' - fromY, '9' - to_x, 'i' - to_y);
  2632.         break;
  2633.     }
  2634.  
  2635.     fromX = fromY = -1;
  2636.  
  2637.     Attention(firstProgramPID);
  2638.     SendToProgram(user_move, toFirstProgFP);
  2639.     strcpy(moveList[currentMove - 1], user_move);
  2640.  
  2641.     if (gameMode == PauseGame)
  2642.       PauseProc(); /* a user move restarts a paused game*/
  2643.  
  2644.     switch (gameMode) {
  2645.           case ForceMoves:
  2646.           case SetupPosition:
  2647.         break;
  2648.           case BeginningOfGame:
  2649.         if (appData.noChessProgram)
  2650.           lastGameMode = gameMode = ForceMoves;
  2651.         else
  2652.           lastGameMode = gameMode = MachinePlaysWhite;
  2653.         ModeHighlight();
  2654.         break;
  2655.           case MachinePlaysWhite:
  2656.           case MachinePlaysBlack:
  2657.           default:
  2658.         break;
  2659.     }
  2660. }
  2661.  
  2662. /* Simple parser for moves from gnuchess. */
  2663. void
  2664. ParseMachineMove(machine_move, move_type, from_x, from_y, to_x, to_y)
  2665.      char *machine_move;
  2666.      ChessMove *move_type;
  2667.      int *from_x, *from_y, *to_x, *to_y;
  2668. {               
  2669.  
  2670.  
  2671. #define no_digit(c) (c < '0' || c > '9' )
  2672.  
  2673.     {                     
  2674.                 if ( no_digit(machine_move[0]) ) {
  2675.  
  2676.           switch ( machine_move[0] ) {
  2677.             case 'P': *from_x = 81; break;
  2678.             case 'L': *from_x = 82; break;
  2679.             case 'N': *from_x = 83; break;
  2680.             case 'S': *from_x = 84; break;
  2681.             case 'G': *from_x = 85; break;
  2682.             case 'B': *from_x = 86; break;
  2683.             case 'R': *from_x = 87; break;
  2684.             case 'K': *from_x = 88; break;
  2685.                         default: *from_x = -1;
  2686.           };
  2687.           *from_y = *from_x;
  2688.           *to_x   = '9' - machine_move[2];
  2689.           *to_y   = 'i' - machine_move[3];
  2690.  
  2691.         } else {
  2692.  
  2693.           *from_x = '9' - machine_move[0] ;
  2694.           *from_y = 'i' - machine_move[1];
  2695.           *to_x = '9' - machine_move[2];
  2696.           *to_y = 'i' - machine_move[3];
  2697.  
  2698.           switch (machine_move[4]) {
  2699.               case '+':
  2700.             *move_type = BLACK_ON_MOVE ?
  2701.               BlackPromotion : WhitePromotion;
  2702.             break;
  2703.               default:
  2704.             *move_type = NormalMove;
  2705.             break;
  2706.           }
  2707.         }          
  2708.     }
  2709. }
  2710.  
  2711. void
  2712. HandleMachineMove(message, fp)
  2713.     char *message;
  2714.         FILE *fp;
  2715. {
  2716.     char machine_move[MSG_SIZ], buf1[MSG_SIZ], buf2[MSG_SIZ];
  2717.     int i, j, from_x, from_y, to_x, to_y;
  2718.     ChessMove move_type;
  2719.  
  2720.     maybeThinking = False;
  2721.  
  2722.     if (strncmp(message, "warning:", 8) == 0) {
  2723.         DisplayMessage(message);
  2724.         return;
  2725.     }
  2726.  
  2727.     /*
  2728.      * If chess program startup fails, exit with an error message.
  2729.      * Attempts to recover here are futile.
  2730.      */
  2731.     if ((StrStr(message, "unknown host") != NULL)
  2732.         || (StrStr(message, "No remote directory") != NULL)
  2733.         || (StrStr(message, "not found") != NULL)
  2734.         || (StrStr(message, "No such file") != NULL)
  2735.         || (StrStr(message, "Permission denied") != NULL)) {
  2736.         fprintf(stderr,
  2737.             "%s: failed to start chess program %s on %s: %s\n",
  2738.             programName,
  2739.             fp == fromFirstProgFP ? appData.firstChessProgram
  2740.                 : appData.secondChessProgram,
  2741.             fp == fromFirstProgFP ? appData.firstHost
  2742.                 : appData.secondHost,
  2743.             message);
  2744.         ShutdownChessPrograms(message);
  2745.         exit(1);
  2746.     }
  2747.  
  2748.     /*
  2749.      * If the move is illegal, cancel it and redraw the board.
  2750.      */
  2751.     if (strncmp(message, "Illegal move", 12) == 0) {
  2752.  
  2753.         if (currentMove <= (whitePlaysFirst ? 1 : 0)) return;
  2754.         if (gameMode == PlayFromGameFile) {
  2755.             /* Stop reading this game file */
  2756.             gameMode = ForceMoves;
  2757.             ModeHighlight();
  2758.         }
  2759.         currentMove--;
  2760.         if ((gameMode == PlayFromGameFile) || 
  2761.             (gameMode == ForceMoves) ||
  2762.             (gameMode == SetupPosition))
  2763.           DisplayClocks(ReDisplayTimers);
  2764.         else
  2765.           DisplayClocks(SwitchTimers);
  2766.         sprintf(buf1, "Illegal move: %s", parseList[currentMove]);
  2767.         DisplayMessage(buf1);
  2768.  
  2769.         /*
  2770.          * Only redraw the squares that have changed.
  2771.          */
  2772.         for (i = 0; i < BOARD_SIZE; i++)
  2773.           for (j = 0; j < BOARD_SIZE; j++) {
  2774.               if (boards[currentMove][i][j] !=
  2775.                   boards[currentMove + 1][i][j])
  2776.                 DrawSquare(i, j, boards[currentMove][i][j]);
  2777.           }
  2778.         UpdateCatched(0,0,False,True, currentMove);
  2779.         UpdateCatched(1,0,False,True, currentMove);
  2780.  
  2781.         XSync(xDisplay, False);
  2782.         return;
  2783.     }
  2784.  
  2785.     if (strncmp(message, "Hint:", 5) == 0) {
  2786.         sscanf(message, "Hint: %s", machine_move);
  2787.         ParseMachineMove(machine_move, &move_type,
  2788.                  &from_x, &from_y, &to_x, &to_y);
  2789.         if ( move_type == WhitePromotion || move_type == BlackPromotion )
  2790.           move_type = MakeAlg(from_x, from_y, to_x, to_y, '+',
  2791.                    currentMove, buf1);
  2792.         else
  2793.           move_type = MakeAlg(from_x, from_y, to_x, to_y, '\000',
  2794.                    currentMove, buf1);
  2795.         sprintf(buf2, "Hint: %s", buf1);
  2796.         DisplayMessage(buf2);
  2797.         return;
  2798.     }
  2799.  
  2800.     /*
  2801.      * win, lose or draw
  2802.      */
  2803.     if (strncmp(message, "Black", 5) == 0) {
  2804.         ShutdownChessPrograms("Black wins");
  2805.         return;
  2806.     } else if (strncmp(message, "White", 5) == 0) {
  2807.         ShutdownChessPrograms("White wins");
  2808.         return;
  2809.     } else if (strncmp(message, "opponent mates!", 15) == 0) {
  2810.         switch (gameMode) {
  2811.               case MachinePlaysWhite:
  2812.             ShutdownChessPrograms("Black wins");
  2813.             break;
  2814.               case MachinePlaysBlack:
  2815.             ShutdownChessPrograms("White wins");
  2816.             break;
  2817.               case TwoMachinesPlay:
  2818.             ShutdownChessPrograms(fp == fromFirstProgFP ?
  2819.                           "Black wins" : "White wins");
  2820.             break;
  2821.               default:
  2822.             /* can't happen */
  2823.             break;
  2824.         }
  2825.         return;
  2826.     } else if (strncmp(message, "computer mates!", 15) == 0) {
  2827.         switch (gameMode) {
  2828.               case MachinePlaysWhite:
  2829.             ShutdownChessPrograms("White wins");
  2830.             break;
  2831.               case MachinePlaysBlack:
  2832.             ShutdownChessPrograms("Black wins");
  2833.             break;
  2834.               case TwoMachinesPlay:
  2835.             ShutdownChessPrograms(fp == fromFirstProgFP ?
  2836.                           "White wins" : "Black wins");
  2837.             break;
  2838.               default:
  2839.             /* can't happen */
  2840.             break;
  2841.         }
  2842.         return;
  2843.     } else if (strncmp(message, "Draw", 4) == 0) {
  2844.         ShutdownChessPrograms("Draw");
  2845.         return;
  2846.     }
  2847.  
  2848.     /*
  2849.      * normal machine reply move
  2850.      */
  2851.     maybeThinking = True;
  2852.     if (StrStr(message, "...") != NULL) {
  2853.         sscanf(message, "%s %s %s", buf1, buf2, machine_move);
  2854.         if (machine_move[0] == '\0')
  2855.             return;
  2856.     } else
  2857.         return; /* ignore noise */
  2858.  
  2859.     strcpy(moveList[currentMove], machine_move);
  2860.  
  2861.     ParseMachineMove(machine_move, &move_type, &from_x, &from_y,
  2862.              &to_x, &to_y);
  2863.  
  2864.     MakeMove(&move_type, from_x, from_y, to_x, to_y);
  2865. #if BLINK_COUNT
  2866.     if ( gameMode != TwoMachinesPlay ) 
  2867.       BlinkSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
  2868. #endif
  2869.  
  2870.     switch (gameMode) {
  2871.           case PauseGame:
  2872.           case EndOfGame:
  2873.           default:
  2874.         break;
  2875.           case ForceMoves:
  2876.           case SetupPosition:
  2877.           case PlayFromGameFile:
  2878.         strncat(machine_move, "\n", 1);
  2879.         SendToProgram(machine_move, toFirstProgFP);
  2880.         break;
  2881.           case TwoMachinesPlay:
  2882.         strncat(machine_move, "\n", 1);
  2883.         if (BLACK_ON_MOVE) {
  2884.             Attention(secondProgramPID);
  2885.             SendToProgram(machine_move, toSecondProgFP);
  2886.             if (firstMove) {
  2887.                 firstMove = False;
  2888.                 SendToProgram(appData.blackString,
  2889.                           toSecondProgFP);
  2890.             }
  2891.         } else {
  2892.             Attention(firstProgramPID);
  2893.             SendToProgram(machine_move, toFirstProgFP);
  2894.             if (firstMove) {
  2895.                 firstMove = False;
  2896.                 SendToProgram(appData.whiteString,
  2897.                           toFirstProgFP);
  2898.             }
  2899.         }
  2900.         break;
  2901.     }
  2902. }
  2903.  
  2904.  
  2905. #if BLINK_COUNT
  2906.  
  2907.  
  2908. static int BlinkCount;
  2909. static int BlinkRow, BlinkCol;
  2910. static ChessSquare BlinkPiece;
  2911.  
  2912.  
  2913. void
  2914. BlinkSquareProc ()
  2915. {
  2916.    if ( BlinkCount-- ) {
  2917.     DrawSquare (BlinkRow,BlinkCol,
  2918.         (BlinkCount & 1) ? EmptySquare : BlinkPiece);
  2919.     blinkSquareXID = XtAppAddTimeOut(appContext,
  2920.         (int) (150),
  2921.         (XtTimerCallbackProc) BlinkSquareProc, NULL);
  2922.    }
  2923. }
  2924.  
  2925.  
  2926. void
  2927. BlinkSquare (row, col, piece)
  2928.     int row, col;
  2929.     ChessSquare piece;
  2930. {
  2931.    BlinkCount = 2*BLINK_COUNT + 1;
  2932.    BlinkRow = row;
  2933.    BlinkCol = col;
  2934.    BlinkPiece = piece;
  2935.    BlinkSquareProc();
  2936. }
  2937.  
  2938.  
  2939. #endif /* BLINK_COUNT */
  2940.  
  2941.  
  2942.  
  2943. void
  2944. ReadGameFile()
  2945. {
  2946.     for (;;) {
  2947.         if (!ReadGameFileProc())
  2948.             return;
  2949.         if (matchMode == MatchOpening)
  2950.             continue;
  2951.         readGameXID = XtAppAddTimeOut(appContext,
  2952.             (int) (1000 * appData.timeDelay),
  2953.             (XtTimerCallbackProc) ReadGameFile, NULL);
  2954.         break;
  2955.     }
  2956. }
  2957.  
  2958. int
  2959. ReadGameFileProc()
  2960. {
  2961.     int from_x, from_y, to_x, to_y, done;
  2962.     ChessMove move_type;
  2963.     char move[MSG_SIZ];
  2964.  
  2965.     if (gameFileFP == NULL)
  2966.         return (int) False;
  2967.  
  2968.     if (gameMode == PauseGame) return True;
  2969.  
  2970.     if (gameMode != PlayFromGameFile) {
  2971.         fclose(gameFileFP);
  2972.         gameFileFP = NULL;
  2973.         return (int) False;
  2974.     }
  2975.  
  2976.     if (commentUp) {
  2977.         XtPopdown(commentShell);
  2978.         XtDestroyWidget(commentShell);
  2979.         commentUp = False;
  2980.     }       
  2981.  
  2982.     parseGameFile ();
  2983.  
  2984.     move_type = (ChessMove) 0;
  2985.  
  2986.     lastGameMode = gameMode;
  2987.     gameMode = ForceMoves;
  2988.     ModeHighlight();
  2989.     DisplayMessage("End of game file");
  2990.  
  2991.     if (readGameXID != 0) {
  2992.         XtRemoveTimeOut(readGameXID);
  2993.         readGameXID = 0;
  2994.     }
  2995.     fclose(gameFileFP);
  2996.     gameFileFP = NULL;
  2997.  
  2998.     return ((int) False);
  2999. }
  3000.  
  3001. /*
  3002.  * MakeMove() displays moves.  If they are illegal, GNU shogi will detect
  3003.  * this and send an Illegal move message.  XShogi will then retract the move.
  3004.  * The clockMode False case is tricky because it displays the player on move.
  3005.  */
  3006. void
  3007. MakeMove(move_type, from_x, from_y, to_x, to_y)
  3008.     ChessMove *move_type;
  3009.     int from_x, from_y, to_x, to_y;
  3010. {
  3011.     char message[MSG_SIZ], movestr[MSG_SIZ];
  3012.     char pieceChar = '\000';
  3013.         ChessSquare piece;
  3014.  
  3015.     CopyBoard(boards[currentMove + 1], boards[currentMove]);
  3016.     CopyCatches(catches[currentMove + 1], catches[currentMove]);
  3017.  
  3018.     forwardMostMove = ++currentMove;
  3019.  
  3020.     if ((gameMode == PlayFromGameFile) || (gameMode == ForceMoves) ||
  3021.         (gameMode == SetupPosition))
  3022.       DisplayClocks(ReDisplayTimers);
  3023.     else
  3024.       DisplayClocks(SwitchTimers);
  3025.     if ( from_x > 80 ) {
  3026.                 int i = from_x - 81, c = (BLACK_ON_MOVE ? 1 : 0);
  3027.                 ChessSquare cpiece = catchedIndexToPiece[c][i];
  3028.         boards[currentMove][to_y][to_x] = cpiece;
  3029.         DrawSquare(to_y, to_x, cpiece);
  3030.         catches[currentMove][c][i]--;
  3031.         UpdateCatched(c, i, False, False, currentMove);
  3032.     } else if (PromotionPossible(from_y,to_y,piece = boards[currentMove][from_y][from_x])) {
  3033.          ChessSquare cpiece = boards[currentMove][to_y][to_x];
  3034.         if ( cpiece != EmptySquare ) {
  3035.           int i = pieceToCatchedIndex[cpiece];
  3036.           int c = (cpiece < WhitePawn );
  3037.           catches[currentMove][c][i]++;
  3038.           UpdateCatched(c, i, True, False, currentMove);
  3039.         }; 
  3040.         if ( *move_type == NormalMove ) {
  3041.             boards[currentMove][to_y][to_x] = piece;
  3042.         } else {
  3043.             boards[currentMove][to_y][to_x] = piece = pieceToPromoted[piece];
  3044.           pieceChar = '+';
  3045.         }
  3046.         boards[currentMove][from_y][from_x] = EmptySquare;
  3047.         DrawSquare(from_y, from_x, boards[currentMove][from_y][from_x]);
  3048.         DrawSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
  3049.         } else { 
  3050.          ChessSquare piece = boards[currentMove][to_y][to_x];
  3051.         if ( piece != EmptySquare ) {
  3052.           int i = pieceToCatchedIndex[piece];
  3053.           int c = (piece < WhitePawn );
  3054.           catches[currentMove][c][i]++;
  3055.           UpdateCatched(c, i, True, False, currentMove);
  3056.         };
  3057.         *move_type = NormalMove;
  3058.         boards[currentMove][to_y][to_x] =
  3059.           boards[currentMove][from_y][from_x];
  3060.         boards[currentMove][from_y][from_x] = EmptySquare;
  3061.         DrawSquare(to_y, to_x, boards[currentMove][to_y][to_x]);
  3062.         DrawSquare(from_y, from_x,
  3063.                boards[currentMove][from_y][from_x]);
  3064.     }
  3065.  
  3066.     
  3067.     if (gameMode == PlayFromGameFile) {
  3068.         sprintf(message, "%d. %s%s", (currentMove + 1) / 2,
  3069.             BLACK_ON_MOVE ? "... " : "", currentMoveString);
  3070.         strcpy(parseList[currentMove - 1], currentMoveString);
  3071.     } else {
  3072.         MakeAlg(from_x, from_y, to_x, to_y, pieceChar,
  3073.             currentMove - 1, movestr);
  3074.         sprintf(message, "%d. %s%s", (currentMove + 1) / 2,
  3075.             BLACK_ON_MOVE ? "... " : "", movestr);
  3076.         strcpy(parseList[currentMove - 1], movestr);
  3077.     }
  3078.  
  3079.     DisplayMessage(message);
  3080.     XSync(xDisplay, False);
  3081. }
  3082.  
  3083. void
  3084. InitChessProgram(host_name, program_name, pid, to, from, xid)
  3085.     char *host_name, *program_name;
  3086.     int *pid;
  3087.     FILE **to, **from;
  3088.     XtIntervalId *xid;
  3089. {
  3090.     char arg_buf[10];
  3091.     char *arg1, *arg2;
  3092.     int to_prog[2], from_prog[2];
  3093.     FILE *from_fp, *to_fp;
  3094.     int dummy_source;
  3095.     XtInputId dummy_id;
  3096. #if     SYSTEM_FIVE || SYSV
  3097.     char *pty_name;
  3098. #endif
  3099.  
  3100.     if (appData.noChessProgram) return;
  3101.  
  3102. #if    SYSTEM_FIVE || SYSV
  3103.     if ((pty_name = PseudoTTY(&to_prog[1])) == NULL) {
  3104.         fprintf(stderr, "%s: can't open pseudo-tty\n", programName);
  3105.         perror("");
  3106.         exit(1);
  3107.     }
  3108.  
  3109.     from_prog[0] = to_prog[1];
  3110.     to_prog[0] = from_prog[1] = open(pty_name, O_RDWR, 0);
  3111. #if    SVR4
  3112.     if (ioctl (to_prog[0], I_PUSH, "ptem") == -1 ||
  3113.         ioctl (to_prog[0], I_PUSH, "ldterm") == -1 ||
  3114.         ioctl (to_prog[0], I_PUSH, "ttcompat") == -1) {
  3115.         fprintf(stderr, "%s: can't ioctl pseudo-tty\n", programName);
  3116.         perror("");
  3117.         exit(1);
  3118.     }
  3119. #endif
  3120. #else
  3121.     signal(SIGPIPE, CatchPipeSignal);
  3122.     pipe(to_prog);
  3123.     pipe(from_prog);
  3124. #endif
  3125.  
  3126.     if ((*pid = fork()) == 0) {
  3127. #if    !SYSTEM_FIVE && !SYSV
  3128.         signal(SIGPIPE, CatchPipeSignal);
  3129. #endif
  3130.         dup2(to_prog[0], 0);
  3131.         dup2(from_prog[1], 1);
  3132.         close(to_prog[0]);
  3133.         close(to_prog[1]);
  3134.         close(from_prog[0]);
  3135.         close(from_prog[1]);
  3136.         dup2(1, fileno(stderr));    /* force stderr to the pipe */
  3137.         if (appData.searchTime != NULL) {
  3138.             sprintf(arg_buf, "%d", searchTime);
  3139.             arg1 = arg_buf;
  3140.             arg2 = (char *) NULL;
  3141.         } else if (appData.searchDepth > 0) {
  3142.             sprintf(arg_buf, "%d", appData.searchDepth);
  3143.             arg1 = "1";
  3144.             arg2 = "9999";
  3145.         } else {
  3146.             sprintf(arg_buf, "%d", appData.movesPerSession);
  3147.             arg1 = arg_buf;
  3148.             arg2 = appData.timeControl;
  3149.         }
  3150.         if (strcmp(host_name, "localhost") == 0) {
  3151.             execlp(program_name, program_name, arg1, arg2,
  3152.                 (char *) NULL);
  3153.         } else {
  3154.             execlp(appData.remoteShell, appData.remoteShell,
  3155.                 host_name, program_name, arg1, arg2,
  3156.                 (char *) NULL);
  3157.         }
  3158.  
  3159.         perror(program_name);
  3160.         exit(1);
  3161.     }
  3162.  
  3163.     close(to_prog[0]);
  3164.     close(from_prog[1]);
  3165.  
  3166.     *from = from_fp = fdopen(from_prog[0], "r");
  3167.     *to = to_fp = fdopen(to_prog[1], "w");
  3168.     setbuf(from_fp, NULL); setbuf(to_fp, NULL);
  3169.  
  3170.     ReceiveFromProgram(from_fp, &dummy_source, &dummy_id); /*"Chess"*/
  3171.     if (*pid == 0) return;
  3172.  
  3173.     *xid = XtAppAddInput(appContext, fileno(from_fp), 
  3174.                  (XtPointer)XtInputReadMask,
  3175.                  (XtInputCallbackProc)ReceiveFromProgram, 
  3176.                  (XtPointer)from_fp);
  3177.  
  3178.     SendToProgram(appData.initString, *to);
  3179.     SendSearchDepth(*to);
  3180. }
  3181.  
  3182. void
  3183. ShutdownChessPrograms(why)
  3184.     char *why;
  3185. {
  3186.     lastGameMode = gameMode;
  3187.     gameMode = EndOfGame;
  3188.     ModeHighlight();
  3189.     CopyBoard(boards[currentMove + 1], boards[currentMove]);
  3190.     CopyCatches(catches[currentMove + 1], catches[currentMove]);
  3191.     strncpy(parseList[currentMove], why, MOVE_LEN);
  3192.     parseList[currentMove][MOVE_LEN-1] = '\000';
  3193.     currentMove++;
  3194.     DisplayMessage(why);
  3195.  
  3196.     if (readGameXID != 0)
  3197.         XtRemoveTimeOut(readGameXID);
  3198.     readGameXID = 0;
  3199.  
  3200.     if (firstProgramPID != 0) {
  3201.         fclose(fromFirstProgFP);
  3202.         fclose(toFirstProgFP);
  3203.         fromFirstProgFP = toFirstProgFP = NULL;
  3204.         if (kill(firstProgramPID, SIGTERM)==0) 
  3205.           wait((union wait *)0);
  3206.  
  3207.     }
  3208.     firstProgramPID = 0;
  3209.  
  3210.     if (firstProgramXID != 0)
  3211.         XtRemoveInput(firstProgramXID);
  3212.     firstProgramXID = 0;
  3213.  
  3214.     if (secondProgramPID != 0) {
  3215.         fclose(fromSecondProgFP);
  3216.         fclose(toSecondProgFP);
  3217.         fromSecondProgFP = toSecondProgFP = NULL;
  3218.         if (kill(secondProgramPID, SIGTERM)==0) 
  3219.           wait((union wait *)0);
  3220.     }
  3221.     secondProgramPID = 0;
  3222.  
  3223.     if (secondProgramXID != 0)
  3224.         XtRemoveInput(secondProgramXID);
  3225.     secondProgramXID = 0;
  3226.  
  3227.     DisplayClocks(StopTimers);
  3228.  
  3229.      if(matchMode != MatchFalse) {
  3230.          if (appData.saveGameFile[0] != '\0') 
  3231.           SaveGameProc(appData.saveGameFile);
  3232.         exit(0);
  3233.      }
  3234. }
  3235.  
  3236. void
  3237. CommentPopUp(label)
  3238.     char *label;
  3239. {
  3240.     Arg args[2];
  3241.     Position x, y;
  3242.     Dimension bw_width, pw_width;
  3243.  
  3244.     if (commentUp) {
  3245.         XtPopdown(commentShell);
  3246.         XtDestroyWidget(commentShell);
  3247.         commentUp = False;
  3248.     }
  3249.  
  3250.     DisplayMessage("Comment");
  3251.  
  3252.     XtSetArg(args[0], XtNwidth, &bw_width);
  3253.     XtGetValues(formWidget, args, 1);
  3254.  
  3255.     XtSetArg(args[0], XtNresizable, True);
  3256.     XtSetArg(args[1], XtNwidth, bw_width - 8);
  3257.  
  3258.     commentShell = XtCreatePopupShell("Comment",
  3259.         transientShellWidgetClass, commandsWidget, args, 2);
  3260.  
  3261.     XtSetArg(args[0], XtNlabel, label);
  3262.  
  3263.     (void) XtCreateManagedWidget("commentLabel", labelWidgetClass,
  3264.         commentShell, args, 1);
  3265.  
  3266.     XtRealizeWidget(commentShell);
  3267.  
  3268.     XtSetArg(args[0], XtNwidth, &pw_width);
  3269.     XtGetValues(commentShell, args, 1);
  3270.  
  3271.     XtTranslateCoords(shellWidget, (bw_width - pw_width) / 2, -50, &x, &y);
  3272.  
  3273.     XtSetArg(args[0], XtNx, x);
  3274.     XtSetArg(args[1], XtNy, y);
  3275.     XtSetValues(commentShell, args, 2);
  3276.  
  3277.     XtPopup(commentShell, XtGrabNone);
  3278.     commentUp = True;
  3279. }
  3280.  
  3281. void
  3282. FileNamePopUp(label, proc)
  3283.     char *label;
  3284.     void (*proc) P((char *name));
  3285. {
  3286.     Arg args[2];
  3287.     Widget popup, dialog;
  3288.     Position x, y;
  3289.     Dimension bw_width, pw_width;
  3290.  
  3291.     fileProc = proc;
  3292.  
  3293.     XtSetArg(args[0], XtNwidth, &bw_width);
  3294.     XtGetValues(boardWidget, args, 1);
  3295.  
  3296.     XtSetArg(args[0], XtNresizable, True);
  3297.     XtSetArg(args[1], XtNwidth, DIALOG_SIZE);
  3298.  
  3299.     popup = XtCreatePopupShell("File Name Prompt",
  3300.         transientShellWidgetClass, commandsWidget, args, 2);
  3301.  
  3302.     XtSetArg(args[0], XtNlabel, label);
  3303.     XtSetArg(args[1], XtNvalue, "");
  3304.  
  3305.     dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
  3306.         popup, args, 2);
  3307.  
  3308.     XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
  3309.     XawDialogAddButton(dialog, "cancel", FileNameCallback,
  3310.                (XtPointer) dialog);
  3311.  
  3312.     XtRealizeWidget(popup);
  3313.  
  3314.     XtSetArg(args[0], XtNwidth, &pw_width);
  3315.     XtGetValues(popup, args, 1);
  3316.  
  3317.     XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2, 10, &x, &y);
  3318.  
  3319.     XtSetArg(args[0], XtNx, x);
  3320.     XtSetArg(args[1], XtNy, y);
  3321.     XtSetValues(popup, args, 2);
  3322.  
  3323.     XtPopup(popup, XtGrabExclusive);
  3324.     filenameUp = True;
  3325.  
  3326.     XtSetKeyboardFocus(shellWidget, popup);
  3327. }
  3328.  
  3329. void
  3330. FileNameCallback(w, client_data, call_data)
  3331.     Widget w;
  3332.     XtPointer client_data, call_data;
  3333. {
  3334.     String name;
  3335.     Arg args[1];
  3336.  
  3337.     XtSetArg(args[0], XtNlabel, &name);
  3338.     XtGetValues(w, args, 1);
  3339.  
  3340.     if (strcmp(name, "cancel") == 0) {
  3341.         XtPopdown(w = XtParent(XtParent(w)));
  3342.         XtDestroyWidget(w);
  3343.         filenameUp = False;
  3344.         ModeHighlight();
  3345.         return;
  3346.     }
  3347.  
  3348.     FileNameAction(w, NULL);
  3349. }
  3350.  
  3351. void
  3352. FileNameAction(w, event)
  3353.     Widget w;
  3354.     XEvent *event;
  3355. {
  3356.     char buf[MSG_SIZ];
  3357.     String name;
  3358.  
  3359.     name = XawDialogGetValueString(w = XtParent(w));
  3360.  
  3361.     if ((name != NULL) && (*name != '\0')) {
  3362.         strcpy(buf, name);
  3363.         XtPopdown(w = XtParent(w));
  3364.         XtDestroyWidget(w);
  3365.         filenameUp = False;
  3366.         (*fileProc)(buf);  /* I can't see a way not
  3367.                       to use a global here */
  3368.         ModeHighlight();
  3369.         return;
  3370.     }
  3371.  
  3372.     XtPopdown(w = XtParent(w));
  3373.     XtDestroyWidget(w);
  3374.     filenameUp = False;
  3375.     ModeHighlight();
  3376. }
  3377.  
  3378.  
  3379.  
  3380.  
  3381. typedef struct {
  3382.     ChessSquare piece;
  3383.     int to_x, to_y;
  3384. } PromotionMoveInfo;
  3385.  
  3386. static PromotionMoveInfo pmi;  /*making this global is gross */
  3387.       
  3388.  
  3389. void
  3390. PromotionPopUp(piece, to_x, to_y)
  3391.          ChessSquare piece;
  3392.          int to_x, to_y;
  3393. {
  3394.     Arg args[2];
  3395.     Widget dialog;
  3396.     Position x, y;
  3397.     Dimension bw_width, bw_height, pw_width, pw_height;
  3398.  
  3399.     pmi.piece = piece;
  3400.     pmi.to_x = to_x;
  3401.     pmi.to_y = to_y;
  3402.  
  3403.     XtSetArg(args[0], XtNwidth, &bw_width);
  3404.     XtSetArg(args[1], XtNheight, &bw_height);
  3405.     XtGetValues(boardWidget, args, 2);
  3406.  
  3407.     XtSetArg(args[0], XtNresizable, True);
  3408.     promotionShell = XtCreatePopupShell("Promotion",
  3409.         transientShellWidgetClass, commandsWidget, args, 1);
  3410.                                       
  3411.     XtSetArg(args[0], XtNlabel, "Promote piece?");
  3412.     dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
  3413.         promotionShell, args, 1);
  3414.  
  3415.     XawDialogAddButton(dialog, "Yes", PromotionCallback, 
  3416.                (XtPointer) dialog);
  3417.     XawDialogAddButton(dialog, "No", PromotionCallback, 
  3418.                (XtPointer) dialog);
  3419.     XawDialogAddButton(dialog, "cancel", PromotionCallback, 
  3420.                (XtPointer) dialog);
  3421.  
  3422.     XtRealizeWidget(promotionShell);
  3423.  
  3424.     XtSetArg(args[0], XtNwidth, &pw_width);
  3425.     XtSetArg(args[1], XtNheight, &pw_height);
  3426.     XtGetValues(promotionShell, args, 2);
  3427.  
  3428.     XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
  3429.               LINE_GAP + squareSize/3 +
  3430.               ((piece == BlackPawn) ^ (flipView) ?
  3431.                0 : 6*(squareSize + LINE_GAP)),
  3432.               &x, &y);
  3433.  
  3434.     XtSetArg(args[0], XtNx, x);
  3435.     XtSetArg(args[1], XtNy, y);
  3436.     XtSetValues(promotionShell, args, 2);
  3437.  
  3438.     XtPopup(promotionShell, XtGrabNone);
  3439.  
  3440.     promotionUp = True;
  3441. }
  3442.  
  3443. void
  3444. PromotionCallback(w, client_data, call_data)
  3445.     Widget w;
  3446.     XtPointer client_data, call_data;
  3447. {
  3448.     String name;
  3449.     Arg args[1];
  3450.     ChessMove move_type;
  3451.  
  3452.     XtSetArg(args[0], XtNlabel, &name);
  3453.     XtGetValues(w, args, 1);
  3454.  
  3455.     XtPopdown(w = XtParent(XtParent(w)));
  3456.     XtDestroyWidget(w);
  3457.     promotionUp = False;
  3458.  
  3459.     if (fromX == -1) return;
  3460.  
  3461.     if (strcmp(name, "Yes") == 0) {
  3462.         if ((int) pmi.piece < (int) WhitePawn)
  3463.           move_type = BlackPromotion;
  3464.         else
  3465.           move_type = WhitePromotion;
  3466.     } else if (strcmp(name, "No") == 0) {
  3467.                 move_type = NormalMove;
  3468.     } else /* strcmp(name, "cancel") == 0 */ {
  3469.         fromX = fromY = -1;
  3470.         return;
  3471.     }
  3472.  
  3473.     MakeMove(&move_type, fromX, fromY, pmi.to_x, pmi.to_y);
  3474.     FinishUserMove(move_type, pmi.to_x, pmi.to_y);
  3475. }
  3476.  
  3477.  
  3478. typedef struct {
  3479.     char mode[2];
  3480.     char name[100];
  3481. } FileModeInfo;
  3482.  
  3483. static FileModeInfo fmi;
  3484.  
  3485.  
  3486. void
  3487. FileModePopUp (name)
  3488.     char *name;
  3489. {
  3490.     Arg args[2];
  3491.     Widget dialog;
  3492.     Position x, y;
  3493.     Dimension bw_width, bw_height, pw_width, pw_height;
  3494.  
  3495.     strcpy(fmi.name,name);
  3496.  
  3497.     XtSetArg(args[0], XtNwidth, &bw_width);
  3498.     XtSetArg(args[1], XtNheight, &bw_height);
  3499.     XtGetValues(boardWidget, args, 2);
  3500.  
  3501.     XtSetArg(args[0], XtNresizable, True);
  3502.     filemodeShell = XtCreatePopupShell("FileMode",
  3503.         transientShellWidgetClass, commandsWidget, args, 1);
  3504.                                       
  3505.     XtSetArg(args[0], XtNlabel, "Append to existing file?");
  3506.     dialog = XtCreateManagedWidget("filemode", dialogWidgetClass,
  3507.         filemodeShell, args, 1);
  3508.  
  3509.     XawDialogAddButton(dialog, "Yes", FileModeCallback, 
  3510.                (XtPointer) dialog);
  3511.     XawDialogAddButton(dialog, "No", FileModeCallback, 
  3512.                (XtPointer) dialog);
  3513.     XawDialogAddButton(dialog, "cancel", FileModeCallback, 
  3514.                (XtPointer) dialog);
  3515.  
  3516.     XtRealizeWidget(filemodeShell);
  3517.  
  3518.     XtSetArg(args[0], XtNwidth, &pw_width);
  3519.     XtSetArg(args[1], XtNheight, &pw_height);
  3520.     XtGetValues(filemodeShell, args, 2);
  3521.  
  3522.     XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
  3523.               LINE_GAP + squareSize/3 +
  3524.               (6*(squareSize + LINE_GAP)),
  3525.               &x, &y);
  3526.  
  3527.     XtSetArg(args[0], XtNx, x);
  3528.     XtSetArg(args[1], XtNy, y);
  3529.     XtSetValues(filemodeShell, args, 2);
  3530.  
  3531.     XtPopup(filemodeShell, XtGrabNone);
  3532.  
  3533.     filemodeUp = True;
  3534. }
  3535.  
  3536. void
  3537. FileModeCallback(w, client_data, call_data)
  3538.     Widget w;
  3539.     XtPointer client_data, call_data;
  3540. {
  3541.     String name;
  3542.     Arg args[1];
  3543.  
  3544.     XtSetArg(args[0], XtNlabel, &name);
  3545.     XtGetValues(w, args, 1);
  3546.  
  3547.     XtPopdown(w = XtParent(XtParent(w)));
  3548.     XtDestroyWidget(w);
  3549.  
  3550.     if (strcmp(name, "Yes") == 0) {
  3551.         strcpy(fmi.mode,"a");
  3552.     } else if (strcmp(name, "No") == 0) {
  3553.                 strcpy(fmi.mode,"w");
  3554.     } else /* strcmp(name, "cancel") == 0 */ {
  3555.                filemodeUp = False;
  3556.            return;
  3557.     }
  3558.  
  3559.     XtPopdown(filemodeShell);
  3560.     XtDestroyWidget(filemodeShell);
  3561.  
  3562.     SaveGameProc(fmi.name);
  3563.  
  3564.     filemodeUp = False;
  3565.  
  3566. }
  3567.  
  3568.  
  3569.  
  3570.  
  3571.  
  3572.  
  3573.  
  3574. void
  3575. SelectCommand(w, client_data, call_data)
  3576.     Widget w;
  3577.     XtPointer client_data, call_data;
  3578. {
  3579.     XawListReturnStruct *list_return = XawListShowCurrent(w);
  3580.  
  3581.     fromX = fromY = -1;
  3582.  
  3583.     if (promotionUp) {
  3584.         XtPopdown(promotionShell);
  3585.         XtDestroyWidget(promotionShell);
  3586.         promotionUp = False;
  3587.     }
  3588.  
  3589.     if ((gameMode == PauseGame)
  3590.         && (list_return->list_index != (int) ButtonPause))
  3591.         PauseProc();
  3592.  
  3593.     switch ((Button) list_return->list_index) {
  3594.           case ButtonQuit:
  3595.         QuitProc();
  3596.         break;
  3597.           case ButtonBackward:
  3598.         BackwardProc();
  3599.         break;
  3600.           case ButtonForward:
  3601.         ForwardProc();
  3602.         break;
  3603.           case ButtonFlipView:
  3604.         FlipProc();
  3605.         break;
  3606.           case ButtonReset:
  3607.         ResetFileProc();
  3608.         ResetProc();
  3609.         break;
  3610.           case ButtonSaveGame:
  3611.         if (appData.saveGameFile[0] == '\0')
  3612.             FileNamePopUp("Filename for saved game?",
  3613.                       SaveGameProc);
  3614.         else
  3615.             SaveGameProc(appData.saveGameFile);
  3616.         break;
  3617.           case ButtonSavePosition:
  3618.         if (appData.savePositionFile[0] == '\0')
  3619.             FileNamePopUp("Filename for saved position?",
  3620.                       SavePositionProc);
  3621.         else
  3622.             SavePositionProc(appData.savePositionFile);
  3623.         break;
  3624.           case ButtonHint:
  3625.         HintProc();
  3626.         break;
  3627. #ifdef notdef
  3628.           case ButtonSwitchSides:
  3629.         SwitchProc();
  3630.         break;
  3631. #endif /*notdef*/
  3632.           case ButtonEditPosition:
  3633.         EditPositionProc();
  3634.         break;        
  3635.           case ButtonLoadPosition:
  3636.         if (gameMode != BeginningOfGame) {
  3637.             DisplayMessage("Press Reset first");
  3638.             break;
  3639.         }
  3640.         if (appData.loadPositionFile == NULL)
  3641.             FileNamePopUp("Position file name?",
  3642.                 VOID_PROC SetupPositionFromFileProc);
  3643.         else
  3644.             (void) SetupPositionFromFileProc(
  3645.               appData.loadPositionFile);
  3646.         break;
  3647.           case ButtonLoadGame:
  3648.         GameProc();
  3649.         break;
  3650.           case ButtonMachineWhite:
  3651.         MachinePlaysWhiteProc();
  3652.         break;
  3653.           case ButtonMachineBlack:
  3654.         MachinePlaysBlackProc();
  3655.         break;
  3656.           case ButtonTwoMachines:
  3657.         TwoMachinesPlayProc();
  3658.         break;
  3659.           case ButtonForceMoves:
  3660.         ForceProc();
  3661.         break;
  3662.           case ButtonPause:
  3663.         PauseProc();
  3664.         break;
  3665.     }
  3666.  
  3667.     if (!filenameUp) ModeHighlight();
  3668. }
  3669.  
  3670. void
  3671. ModeHighlight()
  3672. {
  3673.     switch (gameMode) {
  3674.           case BeginningOfGame:
  3675.         if (appData.noChessProgram)
  3676.           XawListHighlight(commandsWidget, ButtonForceMoves);
  3677.         else
  3678.           XawListHighlight(commandsWidget, ButtonMachineWhite);
  3679.         break;
  3680.           case MachinePlaysWhite:
  3681.         XawListHighlight(commandsWidget, ButtonMachineWhite);
  3682.         break;
  3683.           case MachinePlaysBlack:
  3684.         XawListHighlight(commandsWidget, ButtonMachineBlack);
  3685.         break;
  3686.           case TwoMachinesPlay:
  3687.         XawListHighlight(commandsWidget, ButtonTwoMachines);
  3688.         break;
  3689.           case ForceMoves:
  3690.           case SetupPosition:
  3691.         XawListHighlight(commandsWidget, ButtonForceMoves);
  3692.         break;
  3693.           case PlayFromGameFile:
  3694.         XawListHighlight(commandsWidget, ButtonLoadGame);
  3695.         break;
  3696.           case PauseGame:
  3697.         XawListHighlight(commandsWidget, ButtonPause);
  3698.         break;
  3699.           case EditPosition:
  3700.         XawListHighlight(commandsWidget, ButtonEditPosition);
  3701.         break;
  3702.           case EndOfGame:
  3703.           default:
  3704.         XawListUnhighlight(commandsWidget);
  3705.         break;
  3706.     }
  3707. }
  3708.  
  3709. /*
  3710.  * Button procedures
  3711.  */
  3712. void
  3713. QuitProc()
  3714. {
  3715.     ShutdownChessPrograms("Quitting");
  3716.     exit(0);
  3717. }
  3718.  
  3719. int
  3720. PlayFromGameFileProc(name)
  3721.     char *name;
  3722. {
  3723.     char buf[MSG_SIZ];
  3724.         ChessMove cm;
  3725.  
  3726.     if (gameMode != BeginningOfGame) {
  3727.         DisplayMessage("Press Reset first");
  3728.         return (int) False;
  3729.     }
  3730.  
  3731.     if (appData.loadGameFile != name) {
  3732.         if (appData.loadGameFile)
  3733.             XtFree(appData.loadGameFile);
  3734.         appData.loadGameFile = XtMalloc(strlen(name)+1);
  3735.         strcpy(appData.loadGameFile, name);
  3736.     }
  3737.  
  3738.     if ((gameFileFP = fopen(name, "r")) == NULL) {
  3739.         sprintf(buf, "Can't open %s", name);
  3740.         DisplayMessage(buf);
  3741.         XtFree(appData.loadGameFile);
  3742.         appData.loadGameFile = NULL;
  3743.         return (int) False;
  3744.     }
  3745.  
  3746.     lastGameMode = gameMode = PlayFromGameFile;
  3747.     ModeHighlight();
  3748.     InitPosition();
  3749.     DisplayClocks(StopTimers);
  3750.     if (firstProgramXID == 0)
  3751.       InitChessProgram(appData.firstHost, appData.firstChessProgram,
  3752.                &firstProgramPID, &toFirstProgFP,
  3753.                &fromFirstProgFP, &firstProgramXID);
  3754.     SendToProgram(appData.initString, toFirstProgFP);
  3755.     SendSearchDepth(toFirstProgFP);
  3756.     SendToProgram("force\n", toFirstProgFP);
  3757.  
  3758.     ReadGameFile();
  3759.  
  3760.     return (int) True;
  3761. }
  3762.  
  3763. void
  3764. ResurrectChessProgram()
  3765.      /* Restart the chess program and feed it all the moves made so far.
  3766.     Used when the user wants to back up from end of game, when gnuchess 
  3767.     has already exited.  Assumes gameMode == EndOfGame. */
  3768. {
  3769.     char buf[MSG_SIZ];
  3770.     int i;
  3771.  
  3772.     if (currentMove > 0)
  3773.       currentMove--;  /* delete "Black wins" or the like */
  3774.  
  3775.     InitChessProgram(appData.firstHost, appData.firstChessProgram,
  3776.         &firstProgramPID, &toFirstProgFP, &fromFirstProgFP,
  3777.         &firstProgramXID);
  3778.     SendToProgram(appData.initString, toFirstProgFP);
  3779.     SendSearchDepth(toFirstProgFP);
  3780.     SendToProgram("force\n", toFirstProgFP);
  3781.     gameMode = lastGameMode = ForceMoves;
  3782.     ModeHighlight();
  3783.  
  3784.     i = whitePlaysFirst ? 1 : 0;
  3785.  
  3786.     if (startedFromSetupPosition) {
  3787.         SendBoard(toFirstProgFP, boards[i], catches[i]);
  3788.     }
  3789.  
  3790.     for (; i < currentMove; i++) {
  3791.         strcpy(buf, moveList[i]);
  3792.         SendToProgram(buf, toFirstProgFP);
  3793.     }
  3794.  
  3795.     DisplayClocks(ResetTimers);
  3796.       /* ugh, but there's no way to tell gnuchess what the clocks
  3797.          should read, so the best we can do is bow to its notion.
  3798.          !!gnuchess 4.0 adds a feature that will let us fix this. */
  3799. }
  3800.  
  3801. void
  3802. MachinePlaysWhiteProc()
  3803. {
  3804.     if (gameMode == EditPosition) EditPositionDone();
  3805.  
  3806.     if ((gameMode == EndOfGame) || (gameMode == PlayFromGameFile)
  3807.         || (gameMode == TwoMachinesPlay) || appData.noChessProgram
  3808.         || (gameMode == MachinePlaysWhite))
  3809.         return;
  3810.  
  3811.     if (BLACK_ON_MOVE) {
  3812.         DisplayMessage("It is not White's turn");
  3813.         return;
  3814.     }
  3815.  
  3816.     lastGameMode = gameMode = MachinePlaysWhite;
  3817.     ModeHighlight();
  3818.     SendToProgram(appData.whiteString, toFirstProgFP);
  3819.     DisplayClocks(StartTimers);
  3820. }
  3821.  
  3822. void
  3823. ForwardProc()
  3824. {
  3825.     char buf[MSG_SIZ];
  3826.     int i, j;
  3827.  
  3828.     if (gameMode == BeginningOfGame) {
  3829.         if (currentMove != 0)
  3830.             return;
  3831.         if (appData.loadGameFile != NULL) {
  3832.             if (PlayFromGameFileProc(appData.loadGameFile)) {
  3833.                 XtRemoveTimeOut(readGameXID);
  3834.                 readGameXID = 0;
  3835.             }
  3836.         }
  3837.         return;
  3838.     }
  3839.  
  3840.     if ((gameMode == EndOfGame) || (gameMode == TwoMachinesPlay)
  3841.         || (gameMode == EditPosition)
  3842.         || ((currentMove == 0) && (forwardMostMove == 0)))
  3843.         return;
  3844.  
  3845.     if ((gameMode != PlayFromGameFile) && (currentMove >= forwardMostMove))
  3846.         return;
  3847.  
  3848.     if (gameMode != PauseGame) {
  3849.         PauseProc();
  3850.         if (readGameXID != 0) {
  3851.             XtRemoveTimeOut(readGameXID);
  3852.             readGameXID = 0;
  3853.         }
  3854.     }
  3855.  
  3856.     if (currentMove >= forwardMostMove) {
  3857.         ReadGameFileProc();
  3858.         return;
  3859.     }
  3860.  
  3861.     if ((gameMode != ForceMoves) && (gameMode != PlayFromGameFile) &&
  3862.         (gameMode != SetupPosition)) {
  3863.         lastGameMode = gameMode = ForceMoves;
  3864.         ModeHighlight();
  3865.         SendToProgram("force\n", toFirstProgFP);
  3866.         DisplayClocks(StopTimers);
  3867.     }
  3868.  
  3869.     for (i = 0; i < BOARD_SIZE; i++)
  3870.       for (j = 0; j < BOARD_SIZE; j++)
  3871.         if (boards[currentMove + 1][i][j] != boards[currentMove][i][j])
  3872.           DrawSquare(i, j, boards[currentMove + 1][i][j]);
  3873.  
  3874.         UpdateCatched(0,0,False,True,currentMove+1);
  3875.         UpdateCatched(1,0,False,True,currentMove+1);
  3876.  
  3877.     sprintf(buf, "%d. %s%s", (currentMove / 2) + 1,
  3878.         BLACK_ON_MOVE ? "... " : "", parseList[currentMove]);
  3879.     DisplayMessage(buf);
  3880.     strcpy(buf, moveList[currentMove++]);
  3881.     SendToProgram(buf, toFirstProgFP);
  3882.     DisplayClocks(ReDisplayTimers);
  3883. }
  3884.  
  3885. void
  3886. ResetFileProc()
  3887. {
  3888.     char *buf = "";
  3889.  
  3890.     if (appData.loadGameFile);
  3891.         XtFree(appData.loadGameFile);
  3892.     if (appData.loadPositionFile);
  3893.         XtFree(appData.loadPositionFile);
  3894.     appData.loadGameFile = appData.loadPositionFile = NULL;
  3895.     DisplayName(buf);
  3896.     if (gameFileFP != NULL) {
  3897.         fclose(gameFileFP);
  3898.         gameFileFP = NULL;
  3899.     }
  3900. }
  3901.  
  3902. void
  3903. ResetProc()
  3904. {
  3905.     flipView = False;
  3906.     startedFromSetupPosition = whitePlaysFirst = False;
  3907.     matchMode = MatchFalse;
  3908.     firstMove = True;
  3909.     blackFlag = whiteFlag = False;
  3910.     maybeThinking = False;
  3911.  
  3912.     ShutdownChessPrograms("");
  3913.     lastGameMode = gameMode = BeginningOfGame;
  3914.     ModeHighlight();
  3915.     InitPosition();
  3916.     InitChessProgram(appData.firstHost, appData.firstChessProgram,
  3917.              &firstProgramPID, &toFirstProgFP,
  3918.              &fromFirstProgFP, &firstProgramXID);
  3919.     DisplayClocks(ResetTimers);
  3920.     if (commentUp) {
  3921.         XtPopdown(commentShell);
  3922.         XtDestroyWidget(commentShell);
  3923.         commentUp = False;
  3924.     }
  3925.     if (promotionUp) {
  3926.         XtPopdown(promotionShell);
  3927.         XtDestroyWidget(promotionShell);
  3928.         promotionUp = False;
  3929.     }
  3930. }
  3931.  
  3932.  
  3933.  
  3934.  
  3935. static
  3936. void
  3937. ClearCatches (catches)
  3938.     Catched catches;
  3939. {
  3940.     int c, p;
  3941.     for ( c = 0; c <= 1; c++)
  3942.         for ( p = 0; p <= 7; p++ )
  3943.             catches[c][p] = 0;
  3944. }
  3945.  
  3946.  
  3947.  
  3948.  
  3949.  
  3950. int
  3951. SetupPositionFromFileProc(name)
  3952.     char *name;
  3953. {
  3954.     char *p, line[MSG_SIZ], buf[MSG_SIZ];
  3955.     Board initial_position;
  3956.     Catched initial_catches;
  3957.     FILE *fp;
  3958.     int i, j;
  3959.  
  3960.     if (gameMode != BeginningOfGame) {
  3961.         DisplayMessage("Press Reset first");
  3962.         return (int) False;
  3963.     }
  3964.  
  3965.     if (appData.loadPositionFile != name) {
  3966.         if (appData.loadPositionFile)
  3967.             XtFree(appData.loadPositionFile);
  3968.         appData.loadPositionFile = XtMalloc(strlen(name)+1);
  3969.         strcpy(appData.loadPositionFile, name);
  3970.     }
  3971.  
  3972.     if ((fp = fopen(name, "r")) == NULL) {
  3973.         sprintf(buf, "Can't open %s", name);
  3974.         DisplayMessage(buf);
  3975.         XtFree(appData.loadPositionFile);
  3976.         appData.loadPositionFile = NULL;
  3977.         return (int) False;
  3978.     }
  3979.  
  3980.     lastGameMode = gameMode = SetupPosition;
  3981.     ModeHighlight();
  3982.     startedFromSetupPosition = True;
  3983.  
  3984.     if (firstProgramXID == 0)
  3985.       InitChessProgram(appData.firstHost, appData.firstChessProgram,
  3986.                &firstProgramPID, &toFirstProgFP,
  3987.                &fromFirstProgFP, &firstProgramXID);
  3988.  
  3989.     /*
  3990.      * skip header information in position file
  3991.      */
  3992.     fgets(line, MSG_SIZ, fp);
  3993.     line[strlen(line) - 1] = '\0';
  3994.     DisplayName(line);
  3995.     fgets(line, MSG_SIZ, fp);
  3996.     fgets(line, MSG_SIZ, fp);
  3997.  
  3998.     for (i = BOARD_SIZE - 1; i >= 0; i--) {
  3999.         fgets(line, MSG_SIZ, fp);
  4000.         for (p = line, j = 0; j < BOARD_SIZE; p++) {
  4001.           int promoted;
  4002.             if (*p == '+')
  4003.               {
  4004.                 promoted = True;
  4005.               }              
  4006.             if (*p == ' ')
  4007.               {
  4008.                 promoted = False;
  4009.               }
  4010.             p++;              
  4011.             initial_position[i][j++] = CharToPiece(*p,promoted);
  4012.         }
  4013.     }
  4014.         { int color;
  4015.       for ( color = 0; color <= 1; color++ ) {
  4016.         fscanf(fp, "%i%i%i%i%i%i%i%i\n",
  4017.         &initial_catches[color][pawn],
  4018.         &initial_catches[color][lance],
  4019.         &initial_catches[color][knight],
  4020.         &initial_catches[color][silver],
  4021.         &initial_catches[color][gold],
  4022.         &initial_catches[color][bishop],
  4023.         &initial_catches[color][rook],
  4024.         &initial_catches[color][king]);
  4025.       };
  4026.     }
  4027.  
  4028.     whitePlaysFirst = False;
  4029.         if (!feof(fp)) {
  4030.         fgets(line, MSG_SIZ, fp);
  4031.         if (strncmp(line, "white", strlen("white"))==0)
  4032.           whitePlaysFirst = True;
  4033.     }
  4034.     fclose(fp);
  4035.  
  4036.     if (whitePlaysFirst) {
  4037.         CopyBoard(boards[0], initial_position);
  4038.                 CopyCatches(catches[0], initial_catches);
  4039.         strcpy(moveList[0], " ...\n");
  4040.         strcpy(parseList[0], " ...\n");
  4041.         currentMove = forwardMostMove = 1;
  4042.         CopyBoard(boards[1], initial_position);
  4043.                 CopyCatches(catches[1], initial_catches);
  4044.         SendToProgram("force\n", toFirstProgFP);
  4045.         SendCurrentBoard(toFirstProgFP);
  4046.         DisplayMessage("White to play");
  4047.     } else {
  4048.         currentMove = forwardMostMove = 0;
  4049.         CopyBoard(boards[0], initial_position);
  4050.                 CopyCatches(catches[0], initial_catches);
  4051.         SendCurrentBoard(toFirstProgFP);
  4052.         SendToProgram("force\n", toFirstProgFP);
  4053.         DisplayMessage("Black to play");
  4054.     }
  4055.  
  4056.     DisplayClocks(ResetTimers);
  4057.     DrawPosition(boardWidget, (XExposeEvent *) NULL);
  4058.  
  4059.     return (int) True;
  4060. }
  4061.  
  4062. void
  4063. EditPositionProc()
  4064. {
  4065.     if (gameMode == EditPosition) return;
  4066.  
  4067.     ForceProc();
  4068.     if (gameMode != ForceMoves) return;
  4069.  
  4070.     DisplayName("<-- Press to set side to play next");
  4071.     DisplayMessage("Mouse: 1=drag, 2=black, 3=white");
  4072.  
  4073.     lastGameMode = gameMode = EditPosition;
  4074.     ModeHighlight();
  4075.     if (currentMove > 0)
  4076.       CopyBoard(boards[0], boards[currentMove]);
  4077.     
  4078.     whitePlaysFirst = !BLACK_ON_MOVE;
  4079.     currentMove = forwardMostMove = 0;
  4080. }
  4081.  
  4082. void
  4083. EditPositionDone()
  4084. {
  4085.     startedFromSetupPosition = True;
  4086.     SendToProgram(appData.initString, toFirstProgFP);
  4087.     SendSearchDepth(toFirstProgFP);
  4088.     if (whitePlaysFirst) {
  4089.         strcpy(moveList[0], " ...\n");
  4090.         strcpy(parseList[0], " ...\n");
  4091.         currentMove = forwardMostMove = 1;
  4092.         CopyBoard(boards[1], boards[0]);
  4093.         CopyCatches(catches[1], catches[0]);
  4094.         SendToProgram("force\n", toFirstProgFP);
  4095.         SendCurrentBoard(toFirstProgFP);
  4096.         DisplayName(" ");
  4097.         DisplayMessage("White to play");
  4098.     } else {
  4099.         currentMove = forwardMostMove = 0;
  4100.         SendCurrentBoard(toFirstProgFP);
  4101.         SendToProgram("force\n", toFirstProgFP);
  4102.         DisplayName(" ");
  4103.         DisplayMessage("Black to play");
  4104.     }
  4105.     lastGameMode = gameMode = SetupPosition;
  4106. }
  4107.  
  4108. void
  4109. MachinePlaysBlackProc()
  4110. {
  4111.     if (gameMode == EditPosition) EditPositionDone();
  4112.  
  4113.     if ((gameMode == EndOfGame) || (gameMode == PlayFromGameFile)
  4114.         || (gameMode == TwoMachinesPlay) || appData.noChessProgram
  4115.         || (gameMode == MachinePlaysBlack))
  4116.         return;
  4117.  
  4118.     if (!BLACK_ON_MOVE) {
  4119.         DisplayMessage("It is not Black's turn");
  4120.         return;
  4121.     }
  4122.  
  4123.     lastGameMode = gameMode = MachinePlaysBlack;
  4124.     ModeHighlight();
  4125.     SendToProgram(appData.blackString, toFirstProgFP);
  4126.     DisplayClocks(StartTimers);
  4127. }
  4128.  
  4129. void
  4130. BackwardProc()
  4131. {
  4132.     int i, j;
  4133.     char buf[MSG_SIZ];
  4134.  
  4135.     if ((currentMove <= 0) || (gameMode == TwoMachinesPlay)
  4136.         || (matchMode != MatchFalse) || (gameMode == EditPosition))
  4137.         return;
  4138.  
  4139.     if ((currentMove == 1) && whitePlaysFirst) return;
  4140.  
  4141.     if (gameMode == EndOfGame) ResurrectChessProgram();
  4142.  
  4143.     if ((BLACK_ON_MOVE && gameMode == MachinePlaysBlack)
  4144.         || (!BLACK_ON_MOVE && gameMode == MachinePlaysWhite)) {
  4145.         DisplayMessage("Wait until your turn");
  4146.         return;
  4147.     }
  4148.  
  4149.     Attention(firstProgramPID);
  4150.  
  4151.     SendToProgram("undo\n", toFirstProgFP);
  4152.  
  4153.     currentMove--;
  4154.     if ((gameMode != ForceMoves) && (gameMode != PlayFromGameFile) &&
  4155.         (gameMode != SetupPosition)) {
  4156.         SendToProgram("force\n", toFirstProgFP);
  4157.         lastGameMode = gameMode = ForceMoves;
  4158.         ModeHighlight();
  4159.         DisplayClocks(StopTimers);
  4160.         }
  4161.     DisplayClocks(ReDisplayTimers);
  4162.  
  4163.     if (gameMode != PauseGame && gameMode != ForceMoves) {
  4164.         PauseProc();
  4165.         if (readGameXID != 0) {
  4166.             XtRemoveTimeOut(readGameXID);
  4167.             readGameXID = 0;
  4168.         }
  4169.     }
  4170.  
  4171.     if (currentMove > 0) {
  4172.         sprintf(buf, "%d. %s%s", (currentMove + 1) / 2,
  4173.             BLACK_ON_MOVE ? "... " : "",
  4174.             parseList[currentMove - 1]);
  4175.         DisplayMessage(buf);
  4176.     } else {
  4177.         DisplayMessage("");
  4178.     }
  4179.  
  4180.     for (i = 0; i < BOARD_SIZE; i++)
  4181.         for (j = 0; j < BOARD_SIZE; j++)
  4182.             if (boards[currentMove][i][j] !=
  4183.                 boards[currentMove + 1][i][j]) {
  4184.                 DrawSquare(i, j, boards[currentMove][i][j]);
  4185.             }
  4186.         UpdateCatched(0,0,False,True,currentMove);
  4187.         UpdateCatched(1,0,False,True,currentMove);
  4188. }
  4189.  
  4190. void
  4191. FlipProc()
  4192. {
  4193.     flipView = !flipView;
  4194.     DrawPosition(boardWidget, (XExposeEvent *) NULL);
  4195. }
  4196.  
  4197. void
  4198. SaveGameProc(name)
  4199.     char *name;
  4200. {
  4201.     char buf[MSG_SIZ], black_move[MSG_SIZ], white_move[MSG_SIZ];
  4202.     int i, len, move = 0;
  4203.     time_t tm;
  4204.  
  4205.     if ( !filemodeUp ) {
  4206.       strcpy(fmi.mode,"w");
  4207.       if ((gameFileFP = fopen(name, "r")) != NULL) {
  4208.         fclose(gameFileFP);
  4209.         FileModePopUp(name);
  4210.         return;
  4211.       }
  4212.     }
  4213.  
  4214.     if ((gameFileFP = fopen(name, fmi.mode)) == NULL) {
  4215.         sprintf(buf, "Can't open %s (mode %s)", name, fmi.mode);
  4216.         DisplayMessage(buf);
  4217.         return;
  4218.     }
  4219.  
  4220.     tm = time((time_t *) NULL);
  4221.     gethostname(buf, MSG_SIZ);
  4222.         
  4223. #ifdef FULL_SAVE_GAME 
  4224.     fprintf(gameFileFP, "# %s game file -- %s", programName, ctime(&tm)); 
  4225.     switch (lastGameMode) {
  4226.           case MachinePlaysBlack:
  4227.         fprintf(gameFileFP, "\t%s@%s vs. %s@%s\n",
  4228.             appData.firstChessProgram, appData.firstHost,
  4229.             getpwuid(getuid())->pw_name, buf);
  4230.         break;
  4231.           case MachinePlaysWhite:
  4232.         fprintf(gameFileFP, "\t%s@%s vs. %s@%s\n",
  4233.             getpwuid(getuid())->pw_name, buf,
  4234.             appData.firstChessProgram, appData.firstHost);
  4235.         break;
  4236.           case TwoMachinesPlay:
  4237.         fprintf(gameFileFP, "\t%s@%s vs. %s@%s\n",
  4238.             appData.secondChessProgram, appData.secondHost,
  4239.             appData.firstChessProgram, appData.firstHost);
  4240.         break;
  4241.           default:
  4242.         fprintf(gameFileFP, "\n");
  4243.         break;
  4244.     }
  4245.     fprintf(gameFileFP, "\talgebraic\n");
  4246.  
  4247.     for (i = 0; i < currentMove;) {
  4248.         fprintf(gameFileFP, "%d. %s ", ++move, parseList[i++]);
  4249.         if (i >= currentMove) {
  4250.             fprintf(gameFileFP, "\n");
  4251.             break;
  4252.         }
  4253.         if ((len = strlen(parseList[i])) == 0) {
  4254.             fprintf(gameFileFP, "\n");
  4255.             break;
  4256.         }
  4257.         fprintf(gameFileFP, "%s\n", parseList[i++]);
  4258.     }  
  4259. #else
  4260.     fprintf(gameFileFP, "#"); 
  4261.  
  4262.     for (i = 0; i < currentMove;) {
  4263.         if ( i % 5 == 0 )
  4264.           fprintf(gameFileFP, "\n");
  4265.         fprintf(gameFileFP, "%d. %s ", ++move, parseList[i++]);
  4266.         if (i >= currentMove) {
  4267.             fprintf(gameFileFP, "\n");
  4268.             break;
  4269.         }
  4270.         if ((len = strlen(parseList[i])) == 0) {
  4271.             break;
  4272.         }
  4273.         fprintf(gameFileFP, "%s ", parseList[i++]);
  4274.     }  
  4275.     
  4276.     fprintf(gameFileFP, "\n");
  4277. #endif
  4278.  
  4279.     fclose(gameFileFP);
  4280.     gameFileFP = NULL;
  4281. }
  4282.  
  4283. #ifdef notdef  
  4284. /* unused */
  4285. void
  4286. SwitchProc()
  4287. {
  4288.     if (appData.noChessProgram) return;
  4289.     switch (gameMode) {
  4290.     default:
  4291.         return;
  4292.     case MachinePlaysBlack:
  4293.         if (BLACK_ON_MOVE) {
  4294.             DisplayMessage("Wait until your turn");
  4295.             return;
  4296.         }
  4297.         lastGameMode = gameMode = MachinePlaysWhite;
  4298.         ModeHighlight();
  4299.         break;
  4300.     case BeginningOfGame:
  4301.     case MachinePlaysWhite:
  4302.         if (!BLACK_ON_MOVE) {
  4303.             DisplayMessage("Wait until your turn");
  4304.             return;
  4305.         }
  4306.         if (currentMove == 0) {
  4307.             MachinePlaysBlackProc();
  4308.             return;
  4309.         }
  4310.         lastGameMode = gameMode = MachinePlaysBlack;
  4311.         ModeHighlight();
  4312.         break;
  4313.     }
  4314.  
  4315.     Attention(firstProgramPID);
  4316.     SendToProgram("switch\n", toFirstProgFP);
  4317. }
  4318. #endif /*notdef*/
  4319.  
  4320. void
  4321. ForceProc()
  4322. {
  4323.     switch (gameMode) {
  4324.           case MachinePlaysBlack:
  4325.         if (BLACK_ON_MOVE) {
  4326.             DisplayMessage("Wait until your turn");
  4327.             return;
  4328.         }
  4329.         Attention(firstProgramPID);
  4330.         SendToProgram("force\n", toFirstProgFP);
  4331.         break;
  4332.           case MachinePlaysWhite:
  4333.         if (!BLACK_ON_MOVE) {
  4334.             DisplayMessage("Wait until your turn");
  4335.             return;
  4336.         }
  4337.         Attention(firstProgramPID);
  4338.         SendToProgram("force\n", toFirstProgFP);
  4339.         break;
  4340.           case BeginningOfGame:
  4341.         SendToProgram("force\n", toFirstProgFP);
  4342.         break;
  4343.           case PlayFromGameFile:
  4344.         if (readGameXID != 0) {
  4345.             XtRemoveTimeOut(readGameXID);
  4346.             readGameXID = 0;
  4347.         }
  4348.         if (gameFileFP != NULL) {
  4349.             fclose(gameFileFP);
  4350.             gameFileFP = NULL;
  4351.         }
  4352.         break;
  4353.           case EndOfGame:
  4354.         ResurrectChessProgram();
  4355.         break;
  4356.           case EditPosition:
  4357.         EditPositionDone();
  4358.         break;
  4359.           case SetupPosition:
  4360.         break;
  4361.           default:
  4362.         return;
  4363.     }
  4364.  
  4365.     lastGameMode = gameMode = ForceMoves;
  4366.     ModeHighlight();
  4367.     DisplayClocks(StopTimers);
  4368. }
  4369.  
  4370. void
  4371. HintProc()
  4372. {
  4373.     if (appData.noChessProgram) return;
  4374.     switch (gameMode) {
  4375.     case MachinePlaysBlack:
  4376.         if (BLACK_ON_MOVE) {
  4377.             DisplayMessage("Wait until your turn");
  4378.             return;
  4379.         }
  4380.         break;
  4381.     case BeginningOfGame:
  4382.     case MachinePlaysWhite:
  4383.         if (!BLACK_ON_MOVE) {
  4384.             DisplayMessage("Wait until your turn");
  4385.             return;
  4386.         }
  4387.         break;
  4388.     default:
  4389.         DisplayMessage("No hint available");
  4390.         return;
  4391.     }
  4392.     Attention(firstProgramPID);
  4393.     SendToProgram("hint\n", toFirstProgFP);
  4394. }
  4395.  
  4396. void
  4397. SavePositionProc(name)
  4398.     char *name;
  4399. {
  4400.     char buf[MSG_SIZ], host_name[MSG_SIZ];
  4401.     FILE *fp;
  4402.     time_t tm;
  4403.     int i, j;
  4404.  
  4405.     if ((fp = fopen(name, "w")) == NULL) {
  4406.         sprintf(buf, "Can't open %s", name);
  4407.         DisplayMessage(buf);
  4408.         return;
  4409.     }
  4410.  
  4411.     tm = time((time_t *) NULL);
  4412.     gethostname(host_name, MSG_SIZ);
  4413.  
  4414.     fprintf(fp, "%s position file -- %s", programName, ctime(&tm));
  4415.     switch (lastGameMode) {
  4416.     case MachinePlaysBlack:
  4417.         fprintf(fp, "\t%s@%s vs. %s@%s\n", appData.firstChessProgram,
  4418.             appData.firstHost, getpwuid(getuid())->pw_name,
  4419.             host_name);
  4420.         break;
  4421.     case MachinePlaysWhite:
  4422.         fprintf(fp, "\t%s@%s vs. %s@%s\n", getpwuid(getuid())->pw_name,
  4423.             host_name, appData.firstChessProgram,
  4424.             appData.firstHost);
  4425.         break;
  4426.     case TwoMachinesPlay:
  4427.         fprintf(fp, "\t%s@%s vs. %s@%s\n", appData.secondChessProgram,
  4428.             appData.secondHost, appData.firstChessProgram,
  4429.             appData.firstHost);
  4430.         break;
  4431.     default:
  4432.         fprintf(fp, "\n");
  4433.         break;
  4434.     }
  4435.     fprintf(fp, "\n");
  4436.  
  4437.     for (i = BOARD_SIZE - 1; i >= 0; i--) {
  4438.         for (j = 0; j < BOARD_SIZE; j++) {
  4439.             if ( pieceIsPromoted[(int) boards[currentMove][i][j]] )
  4440.                 fprintf(fp,"%c",'+');
  4441.             else
  4442.                 fprintf(fp,"%c",' ');
  4443.             fprintf(fp, "%c",
  4444.                 pieceToChar[(int) boards[currentMove][i][j]]);
  4445.             if (j == BOARD_SIZE - 1) 
  4446.               fputc('\n', fp);
  4447.         }
  4448.     }
  4449.     { int color;
  4450.       for (color = 0; color <= 1; color++)
  4451.         { 
  4452.          fprintf(fp,"%i %i %i %i %i %i %i %i\n",
  4453.             catches[currentMove][color][pawn],
  4454.             catches[currentMove][color][lance],
  4455.             catches[currentMove][color][knight],
  4456.             catches[currentMove][color][silver],
  4457.             catches[currentMove][color][gold],
  4458.             catches[currentMove][color][bishop],
  4459.             catches[currentMove][color][rook],
  4460.             catches[currentMove][color][king]);
  4461.             };
  4462.         }
  4463.  
  4464.     if ((gameMode == EditPosition) ? !whitePlaysFirst : BLACK_ON_MOVE)
  4465.       fprintf(fp, "black to play\n");
  4466.     else
  4467.       fprintf(fp, "white to play\n");
  4468.  
  4469.     fclose(fp);
  4470. }
  4471.  
  4472. void
  4473. TwoMachinesPlayProc()
  4474. {
  4475.     int i;
  4476.     MatchMode matchKind;
  4477.  
  4478.     if ((gameMode == EndOfGame) || (gameMode == TwoMachinesPlay)
  4479.         || appData.noChessProgram)
  4480.         return;
  4481.  
  4482.     if (matchMode == MatchFalse) {
  4483.         switch (gameMode) {
  4484.               case PauseGame:
  4485.               case PlayFromGameFile:
  4486.             return;
  4487.               case MachinePlaysBlack:
  4488.               case MachinePlaysWhite:
  4489.             ForceProc();
  4490.             if (gameMode != ForceMoves) return;
  4491.             matchKind = MatchOpening;
  4492.             break;
  4493.               case ForceMoves:
  4494.             matchKind = MatchOpening;
  4495.             break;
  4496.               case SetupPosition:
  4497.             matchKind = MatchPosition;
  4498.             break;
  4499.               case EditPosition:
  4500.             EditPositionDone();
  4501.             matchKind = MatchPosition;
  4502.             break;
  4503.               case BeginningOfGame:
  4504.               default:
  4505.             matchKind = MatchInit;
  4506.             break;
  4507.         }
  4508.     } else {
  4509.         matchKind = matchMode;
  4510.     }
  4511.  
  4512.     flipView = False;
  4513.     firstMove = False;
  4514.     DisplayClocks(ResetTimers);
  4515.     DisplayClocks(StartTimers);
  4516.  
  4517.     switch (matchKind) {
  4518.           case MatchOpening:
  4519.         if (firstProgramXID == 0) {
  4520.             if (appData.loadGameFile == NULL) {
  4521.                 DisplayMessage("Select game file first");
  4522.                 return;
  4523.             }
  4524.             InitChessProgram(appData.firstHost,
  4525.                      appData.firstChessProgram,
  4526.                      &firstProgramPID, &toFirstProgFP,
  4527.                      &fromFirstProgFP, &firstProgramXID);
  4528.             if (!PlayFromGameFileProc(appData.loadGameFile)) {
  4529.                 ShutdownChessPrograms("Bad game file");
  4530.                 return;
  4531.             }
  4532.             DrawPosition(boardWidget, (XExposeEvent *) NULL);
  4533.         }
  4534.         InitChessProgram(appData.secondHost,
  4535.                  appData.secondChessProgram,
  4536.                  &secondProgramPID, &toSecondProgFP,
  4537.                  &fromSecondProgFP, &secondProgramXID);
  4538.         if (startedFromSetupPosition) {
  4539.             if (whitePlaysFirst) {
  4540.                 i = 1;
  4541.                 SendToProgram("force\n", toSecondProgFP);
  4542.                 SendBoard(toSecondProgFP, boards[i], catches[i]);
  4543.             } else {
  4544.                 i = 0;
  4545.                 SendBoard(toSecondProgFP, boards[i], catches[i]);
  4546.                 SendToProgram("force\n", toSecondProgFP);
  4547.             }
  4548.         } else {
  4549.             i = 0;
  4550.             SendToProgram("force\n", toSecondProgFP);
  4551.         }
  4552.         for (; i < currentMove; i++)
  4553.             SendToProgram(moveList[i], toSecondProgFP);
  4554.         lastGameMode = gameMode = TwoMachinesPlay;
  4555.         ModeHighlight();
  4556.         firstMove = True;
  4557.         if (BLACK_ON_MOVE)
  4558.           SendToProgram(appData.blackString, toSecondProgFP);
  4559.         else
  4560.           SendToProgram(appData.whiteString, toFirstProgFP);
  4561.         break;
  4562.  
  4563.           case MatchPosition:
  4564.         if (firstProgramXID == 0) {
  4565.             if (appData.loadPositionFile == NULL) {
  4566.                 DisplayMessage("Select position file first");
  4567.                 return;
  4568.             }
  4569.             InitChessProgram(appData.firstHost,
  4570.                      appData.firstChessProgram,
  4571.                      &firstProgramPID, &toFirstProgFP,
  4572.                      &fromFirstProgFP, &firstProgramXID);
  4573.             if (!SetupPositionFromFileProc(
  4574.                         appData.loadPositionFile))
  4575.                 return;
  4576.         }
  4577.         InitChessProgram(appData.secondHost,
  4578.                  appData.secondChessProgram,
  4579.                  &secondProgramPID, &toSecondProgFP,
  4580.                  &fromSecondProgFP, &secondProgramXID);
  4581.         if (whitePlaysFirst)
  4582.           SendToProgram("force\n", toSecondProgFP);
  4583.         SendCurrentBoard(toSecondProgFP);
  4584.         lastGameMode = gameMode = TwoMachinesPlay;
  4585.         ModeHighlight();
  4586.         firstMove = True;
  4587.         if (BLACK_ON_MOVE)
  4588.           SendToProgram(appData.blackString, toSecondProgFP);
  4589.         else
  4590.           SendToProgram(appData.whiteString, toFirstProgFP);
  4591.         break;
  4592.  
  4593.           case MatchInit:
  4594.         InitPosition();
  4595.         if (firstProgramXID == 0)
  4596.             InitChessProgram(appData.firstHost,
  4597.                      appData.firstChessProgram,
  4598.                      &firstProgramPID, &toFirstProgFP,
  4599.                      &fromFirstProgFP, &firstProgramXID);
  4600.         InitChessProgram(appData.secondHost,
  4601.                  appData.secondChessProgram,
  4602.                  &secondProgramPID, &toSecondProgFP,
  4603.                  &fromSecondProgFP, &secondProgramXID);
  4604.         lastGameMode = gameMode = TwoMachinesPlay;
  4605.         ModeHighlight();
  4606.         SendToProgram(appData.blackString, toSecondProgFP);
  4607.  
  4608.           default:
  4609.         break;
  4610.     }
  4611. }
  4612.  
  4613. void
  4614. PauseProc()
  4615. {
  4616.     static GameMode previous_mode = PauseGame;
  4617.  
  4618.     switch (gameMode) {
  4619.           case ForceMoves:
  4620.           case EndOfGame:
  4621.           case SetupPosition:
  4622.           case EditPosition:
  4623.           default:
  4624.         return;
  4625.           case PauseGame:
  4626.         gameMode = previous_mode;
  4627.         ModeHighlight();
  4628.         previous_mode = PauseGame;
  4629.         DisplayClocks(StartTimers);
  4630.         DisplayMessage("");
  4631.         break;
  4632.           case PlayFromGameFile:
  4633.         if (readGameXID == 0) {
  4634.             readGameXID =
  4635.               XtAppAddTimeOut(appContext,
  4636.                 (int) (1000 * appData.timeDelay),
  4637.                 (XtTimerCallbackProc) ReadGameFile, NULL);
  4638.         } else {
  4639.             XtRemoveTimeOut(readGameXID);
  4640.             readGameXID = 0;
  4641.         }
  4642.         DisplayMessage("Pausing");
  4643.         break;
  4644.           case BeginningOfGame:
  4645.           case MachinePlaysBlack:
  4646.           case MachinePlaysWhite:
  4647.           case TwoMachinesPlay:
  4648.         if (currentMove == 0)    /* don't pause if no one has moved */
  4649.             return;
  4650.         previous_mode = gameMode;
  4651.         gameMode = PauseGame;
  4652.         ModeHighlight();
  4653.         DisplayClocks(StopTimers);
  4654.         DisplayMessage("Pausing");
  4655.         break;
  4656.     }
  4657. }
  4658.  
  4659. void
  4660. GameProc()
  4661. {
  4662.     if (gameMode != BeginningOfGame) {
  4663.         DisplayMessage("Press Reset first");
  4664.         return;
  4665.     }
  4666.     if (appData.loadGameFile == NULL)
  4667.         FileNamePopUp("Game file name?",
  4668.                   VOID_PROC PlayFromGameFileProc);
  4669.     else
  4670.         (void) PlayFromGameFileProc(appData.loadGameFile);
  4671. }
  4672.  
  4673. void
  4674. Iconify()
  4675. {
  4676.     Arg args[1];
  4677.  
  4678.  
  4679.     fromX = fromY = -1;
  4680.  
  4681.     XtSetArg(args[0], XtNiconic, True);
  4682.     XtSetValues(shellWidget, args, 1);
  4683. }
  4684.  
  4685. void
  4686. SendToProgram(message, fp)
  4687.     char *message;
  4688.     FILE *fp;
  4689. {
  4690.     if (fp == NULL) return;
  4691.     lastMsgFP = fp;
  4692.  
  4693.     if (xshogiDebug)
  4694.         fprintf(stderr, "Sending to %s: %s\n",
  4695.             fp == toFirstProgFP ? "first" : "second", message);
  4696.  
  4697.     if (message[strlen(message) - 1] != '\n')
  4698.         fprintf(fp, "\n%s\n", message);
  4699.     else
  4700.         fputs(message, fp);
  4701.     fflush(fp);
  4702. }
  4703.  
  4704. void
  4705. ReceiveFromProgram(fp, source, id)
  4706.     FILE *fp;
  4707.         int *source;
  4708.         XtInputId *id;
  4709. {
  4710.     char message[MSG_SIZ], *end_str;
  4711.  
  4712.     if (fgets(message, MSG_SIZ, fp) == NULL) {
  4713.         sprintf(message,
  4714.             "%s chess program (%s) exited unexpectedly",
  4715.             fp == fromFirstProgFP ? "first" : "second",
  4716.             fp == fromFirstProgFP ? appData.firstChessProgram
  4717.                 : appData.secondChessProgram);
  4718.         fprintf(stderr, "%s: %s\n", programName, message);
  4719.         ShutdownChessPrograms(message);
  4720.         return;
  4721.     }
  4722.  
  4723.     if ((end_str = (char *) strchr(message, '\r')) != NULL)
  4724.         *end_str = '\0';
  4725.     if ((end_str = (char *) strchr(message, '\n')) != NULL)
  4726.         *end_str = '\0';
  4727.  
  4728.     if (xshogiDebug)
  4729.         fprintf(stderr, "Received from %s: %s\n",
  4730.             fp == fromFirstProgFP ? "first" : "second", message);
  4731.     HandleMachineMove(message, fp);
  4732. }
  4733.  
  4734. void
  4735. SendSearchDepth(fp)
  4736.     FILE *fp;
  4737. {
  4738.     char message[MSG_SIZ];
  4739.  
  4740.     if (appData.searchDepth <= 0) return;
  4741.  
  4742.     sprintf(message, "depth\n%d\nhelp\n", appData.searchDepth);
  4743.       /* note kludge: "help" command forces gnuchessx to print
  4744.          out something that ends with a newline. */
  4745.     SendToProgram(message, fp);
  4746. }
  4747.  
  4748. void
  4749. DisplayMessage(message)
  4750.     char *message;
  4751. {
  4752.     Arg arg;
  4753.  
  4754.     XtSetArg(arg, XtNlabel, message);
  4755.     XtSetValues(messageWidget, &arg, 1);
  4756. }
  4757.  
  4758. void
  4759. DisplayName(name)
  4760.     char *name;
  4761. {
  4762.     Arg arg;
  4763.  
  4764.     XtSetArg(arg, XtNlabel, name);
  4765.     XtSetValues(nameWidget, &arg, 1);
  4766. }
  4767.  
  4768. /*
  4769.  * This routine sends a SIGINT (^C interrupt) to gnuchess to awaken it
  4770.  * if it might be busy thinking on our time.  This normally isn't needed,
  4771.  * but is useful on systems where the FIONREAD ioctl doesn't work (such 
  4772.  * as ESIX), since on those systems the gnuchess feature that lets you 
  4773.  * interrupt its thinking just by typing a command does not work.
  4774.  *
  4775.  * In the future, similar code could be used to stop gnuchess and make
  4776.  * it move immediately when it is thinking about its own move; this could
  4777.  * be useful if we want to make Backward or ForceMoves work while gnuchess
  4778.  * is thinking. --t.mann
  4779.  */
  4780. void
  4781. Attention(pid)
  4782.      int pid;
  4783. {
  4784. #if defined(ATTENTION) || defined(ESIX) || !defined(FIONREAD)
  4785.     if (appData.noChessProgram || (pid == 0)) return;
  4786.     switch (gameMode) {
  4787.           case MachinePlaysBlack:
  4788.           case MachinePlaysWhite:
  4789.           case TwoMachinesPlay:
  4790.         if (currentMove > (whitePlaysFirst ? 2 : 1) && maybeThinking) {
  4791.             if (xshogiDebug)
  4792.               fprintf(stderr, "Sending SIGINT to %s\n",
  4793.                 pid == firstProgramPID ? "first" : "second");
  4794.  
  4795.             (void) kill(pid, SIGINT); /* stop it thinking */
  4796.         }
  4797.         break;
  4798.     }
  4799. #endif /*ATTENTION*/
  4800. }
  4801.  
  4802. void
  4803. CheckFlags()
  4804. {
  4805.     if (blackTimeRemaining <= 0) {
  4806.         blackTimeRemaining = 0;
  4807.         if (!blackFlag) {
  4808.             blackFlag = True;
  4809.             if (whiteFlag)
  4810.               DisplayName("  Both flags have fallen");
  4811.             else
  4812.               DisplayName("  Black's flag has fallen");
  4813.         }
  4814.     }
  4815.     if (whiteTimeRemaining <= 0) {
  4816.         whiteTimeRemaining = 0;
  4817.         if (!whiteFlag) {
  4818.             whiteFlag = True;
  4819.             if (blackFlag)
  4820.               DisplayName("  Both flags have fallen");
  4821.             else
  4822.               DisplayName("  White's flag has fallen");
  4823.         }
  4824.     }
  4825. }
  4826.  
  4827. void
  4828. CheckTimeControl()
  4829. {
  4830.     if (!appData.clockMode) return;
  4831.     if (currentMove == 0) return;
  4832.     /*
  4833.      * add time to clocks when time control is achieved
  4834.      */
  4835.     if ((currentMove % (appData.movesPerSession * 2)) == 0) {
  4836.  
  4837.         if (blackTimeRemaining > 0)
  4838.         blackTimeRemaining += timeControl;
  4839.  
  4840.         if (whiteTimeRemaining > 0)
  4841.         whiteTimeRemaining += timeControl;
  4842.     }
  4843. }
  4844.  
  4845. void
  4846. DisplayLabels()
  4847. {
  4848.     DisplayTimerLabel(blackTimerWidget, "Black",
  4849.               blackTimeRemaining);
  4850.     DisplayTimerLabel(whiteTimerWidget, "White",
  4851.               whiteTimeRemaining);
  4852. }
  4853.  
  4854. #ifdef HAS_GETTIMEOFDAY
  4855. static struct timeval tickStartTV;
  4856. static int tickLength;
  4857.  
  4858. int
  4859. PartialTickLength()
  4860. {
  4861.     struct timeval tv;
  4862.     struct timezone tz;
  4863.     int ptl;
  4864.  
  4865.     gettimeofday(&tv, &tz);
  4866.     ptl = ( (tv.tv_sec - tickStartTV.tv_sec)*1000000 +
  4867.             (tv.tv_usec - tickStartTV.tv_usec) + 500 ) / 1000;
  4868.     if (ptl > tickLength) ptl = tickLength;
  4869.     return ptl;
  4870. }
  4871. #else /*!HAS_GETTIMEOFDAY*/
  4872. #define tickLength 1000
  4873. #endif /*HAS_GETTIMEOFDAY*/
  4874.  
  4875. /*
  4876.  * DisplayClocks manages the game clocks.
  4877.  *
  4878.  * In tournament play, white starts the clock and then black makes a move.
  4879.  * We give the human user a slight advantage if he is playing black---the
  4880.  * clocks don't run until he makes his first move, so it takes zero time.
  4881.  * Also, DisplayClocks doesn't account for network lag so it could get
  4882.  * out of sync with GNU Shogi's clock -- but then, referees are always right.
  4883.  */
  4884. void
  4885. DisplayClocks(clock_mode)
  4886.     int clock_mode;
  4887. {
  4888. #ifdef HAS_GETTIMEOFDAY
  4889.     struct timezone tz;
  4890. #endif /*HAS_GETTIMEOFDAY*/
  4891.     long timeRemaining;
  4892.  
  4893.     switch (clock_mode) {
  4894.           case ResetTimers:
  4895.         /* Stop clocks and reset to a fresh time control */
  4896.         if (timerXID != 0) {
  4897.             XtRemoveTimeOut(timerXID);
  4898.             timerXID = 0;
  4899.         }
  4900.         blackTimeRemaining = timeControl;
  4901.         whiteTimeRemaining = timeControl;
  4902.         if (blackFlag || whiteFlag) {
  4903.             DisplayName("");
  4904.             blackFlag = whiteFlag = False;
  4905.         }
  4906.         DisplayLabels();
  4907.         break;
  4908.  
  4909.           case DecrementTimers:
  4910.         /* Decrement running clock to next 1-second boundary */
  4911.         if (gameMode == PauseGame) return;
  4912.         if (!appData.clockMode) return;
  4913.  
  4914.         if (BLACK_ON_MOVE) 
  4915.           timeRemaining = blackTimeRemaining -= tickLength;
  4916.         else 
  4917.           timeRemaining = whiteTimeRemaining -= tickLength;
  4918.  
  4919.         CheckFlags();
  4920.         DisplayLabels();
  4921.         if (timeRemaining == 0) return;
  4922.  
  4923. #ifdef HAS_GETTIMEOFDAY
  4924.         tickLength = (timeRemaining <= 1000) ? 100 : 1000;
  4925.         gettimeofday(&tickStartTV, &tz);
  4926. #endif /*HAS_GETTIMEOFDAY*/
  4927.         timerXID =
  4928.           XtAppAddTimeOut(appContext, tickLength,
  4929.             (XtTimerCallbackProc) DisplayClocks,
  4930.             (XtPointer) DecrementTimers);
  4931.         break;
  4932.  
  4933.           case SwitchTimers:
  4934.         /* A player has just moved, so stop the previously running
  4935.            clock and start the other one. */
  4936.         if (timerXID != 0) {
  4937.             XtRemoveTimeOut(timerXID);
  4938.             timerXID = 0;
  4939. #ifdef HAS_GETTIMEOFDAY
  4940.             if (appData.clockMode) {
  4941.                 if (BLACK_ON_MOVE)
  4942.                   whiteTimeRemaining -= PartialTickLength();
  4943.                 else
  4944.                   blackTimeRemaining -= PartialTickLength();
  4945.                 CheckFlags();
  4946.             }
  4947. #endif /*HAS_GETTIMEOFDAY*/
  4948.         }
  4949.  
  4950.         CheckTimeControl();
  4951.         DisplayLabels();
  4952.         if (!appData.clockMode) return;
  4953.  
  4954.         timeRemaining = BLACK_ON_MOVE ?
  4955.           blackTimeRemaining : whiteTimeRemaining;
  4956.         if (timeRemaining == 0) return;
  4957. #ifdef HAS_GETTIMEOFDAY
  4958.         tickLength = (timeRemaining <= 1000) ?
  4959.           ((timeRemaining-1) % 100) + 1 :
  4960.           ((timeRemaining-1) % 1000) + 1;
  4961.         gettimeofday(&tickStartTV, &tz);
  4962. #endif /*HAS_GETTIMEOFDAY*/
  4963.         timerXID =
  4964.           XtAppAddTimeOut(appContext, tickLength,
  4965.             (XtTimerCallbackProc) DisplayClocks,
  4966.             (XtPointer) DecrementTimers);
  4967.         break;
  4968.  
  4969.           case ReDisplayTimers:
  4970.         /* Display current clock values */
  4971.         DisplayLabels();
  4972.         break;
  4973.  
  4974.           case StopTimers:
  4975.         /* Stop both clocks */
  4976.         if (timerXID == 0)
  4977.             return;
  4978.         XtRemoveTimeOut(timerXID);
  4979.         timerXID = 0;
  4980.         if (!appData.clockMode) return;
  4981. #ifdef HAS_GETTIMEOFDAY
  4982.         if (BLACK_ON_MOVE)
  4983.           whiteTimeRemaining -= PartialTickLength();
  4984.         else
  4985.           blackTimeRemaining -= PartialTickLength();
  4986.         CheckFlags();
  4987.         DisplayLabels();
  4988. #endif /*HAS_GETTIMEOFDAY*/
  4989.         break;
  4990.  
  4991.           case StartTimers:
  4992.         /* Start clock of player on move, if not already running. */
  4993.         if (timerXID != 0)
  4994.             return;
  4995.  
  4996.         DisplayLabels();
  4997.         if (!appData.clockMode) return;
  4998.  
  4999.         timeRemaining = BLACK_ON_MOVE ?
  5000.           blackTimeRemaining : whiteTimeRemaining;
  5001.         if (timeRemaining == 0) return;
  5002. #ifdef HAS_GETTIMEOFDAY
  5003.         tickLength = (timeRemaining <= 1000) ?
  5004.           ((timeRemaining-1) % 100) + 1 :
  5005.           ((timeRemaining-1) % 1000) + 1;
  5006.         gettimeofday(&tickStartTV, &tz);
  5007. #endif /*HAS_GETTIMEOFDAY*/
  5008.         timerXID =
  5009.           XtAppAddTimeOut(appContext, tickLength,
  5010.             (XtTimerCallbackProc) DisplayClocks,
  5011.             (XtPointer)DecrementTimers);
  5012.         break;
  5013.     }
  5014. }
  5015.  
  5016. void
  5017. DisplayTimerLabel(w, color, timer)
  5018.     Widget w;
  5019.     char *color;
  5020.     long timer;
  5021. {
  5022.     char buf[MSG_SIZ];
  5023.     Arg args[3];
  5024.  
  5025.     if (appData.clockMode) {
  5026.         sprintf(buf, "%s: %s", color, TimeString(timer));
  5027.         XtSetArg(args[0], XtNlabel, buf);
  5028.     } else
  5029.         XtSetArg(args[0], XtNlabel, color);
  5030.  
  5031.     if (((color[0] == 'W') && BLACK_ON_MOVE)
  5032.         || ((color[0] == 'B') && !BLACK_ON_MOVE)) {
  5033.         XtSetArg(args[1], XtNbackground, timerForegroundPixel);
  5034.         XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
  5035.     } else {
  5036.         XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
  5037.         XtSetArg(args[2], XtNforeground, timerForegroundPixel);
  5038.     }
  5039.  
  5040.     XtSetValues(w, args, 3);
  5041. }
  5042.  
  5043. char *
  5044. TimeString(tm)
  5045.     long tm;
  5046. {
  5047.     int second, minute, hour, day;
  5048.     static char buf[32];
  5049.  
  5050.     if (tm > 0 && tm <= 900) {
  5051.         /* convert milliseconds to tenths, rounding up */
  5052.         sprintf(buf, " 0.%1d ", (tm+99)/100);
  5053.         return buf;
  5054.     }
  5055.  
  5056.     /* convert milliseconds to seconds, rounding up */
  5057.     tm = (tm + 999) / 1000; 
  5058.  
  5059.     if (tm >= (60 * 60 * 24)) {
  5060.         day = (int) (tm / (60 * 60 * 24));
  5061.         tm -= day * 60 * 60 * 24;
  5062.     } else
  5063.         day = 0;
  5064.  
  5065.     if (tm >= (60 * 60)) {
  5066.         hour = (int) (tm / (60 * 60));
  5067.         tm -= hour * 60 * 60;
  5068.     } else
  5069.         hour = 0;
  5070.  
  5071.     if (tm >= 60) {
  5072.         minute = (int) (tm / 60);
  5073.         tm -= minute * 60;
  5074.     } else
  5075.         minute = 0;
  5076.  
  5077.     second = tm % 60;
  5078.  
  5079.     if (day > 0)
  5080.         sprintf(buf, " %d:%02d:%02d:%02d ", day, hour, minute, second);
  5081.     else if (hour > 0)
  5082.         sprintf(buf, " %d:%02d:%02d ", hour, minute, second);
  5083.     else
  5084.         sprintf(buf, " %2d:%02d ", minute, second);
  5085.  
  5086.     return buf;
  5087. }
  5088.  
  5089. void
  5090. Usage()
  5091. {
  5092.     fprintf(stderr, "Usage: %s\n", programName);
  5093.     fprintf(stderr, "\tstandard Xt options\n");
  5094.     fprintf(stderr, "\t-iconic\n");
  5095.     fprintf(stderr, "\t-tc or -timeControl minutes[:seconds]\n");
  5096.     fprintf(stderr, "\t-mps or -movesPerSession moves\n");
  5097.     fprintf(stderr, "\t-st or -searchTime minutes[:seconds]\n");
  5098.     fprintf(stderr, "\t-sd or -searchDepth number\n");
  5099.     fprintf(stderr, "\t-clock or -clockMode (True | False)\n");
  5100.     fprintf(stderr, "\t-td or -timeDelay seconds\n");
  5101.     fprintf(stderr, "\t-ncp or -noChessProgram (True | False)\n");
  5102.     fprintf(stderr, "\t-fcp or -firstChessProgram program_name\n");
  5103.     fprintf(stderr, "\t-scp or -secondChessProgram program_name\n");
  5104.     fprintf(stderr, "\t-fh or -firstHost host_name\n");
  5105.     fprintf(stderr, "\t-sh or -secondHost host_name\n");
  5106.     fprintf(stderr, "\t-rsh or -remoteShell shell_name\n");
  5107.     fprintf(stderr,
  5108.         "\t-mm or -matchMode (False | Init | Position | Opening)\n");
  5109.     fprintf(stderr, "\t-lgf or -loadGameFile file_name\n");
  5110.     fprintf(stderr, "\t-lpf or -loadPositionFile file_name\n");
  5111.     fprintf(stderr, "\t-sgf or -saveGameFile file_name\n");
  5112.     fprintf(stderr, "\t-spf or -savePositionFile file_name\n");
  5113.     fprintf(stderr, "\t-size or -boardSize (Large | Medium | Small)\n");
  5114.     fprintf(stderr, "\t-coords or -showCoords (True | False)\n");
  5115.     fprintf(stderr, "\t-mono or -monoMode (True | False)\n");
  5116.     fprintf(stderr, "\t-wpc or -blackPieceColor color\n");
  5117.     fprintf(stderr, "\t-bpc or -whitePieceColor color\n");
  5118.     fprintf(stderr, "\t-lsc or -lightSquareColor color\n");
  5119.     fprintf(stderr, "\t-dsc or -darkSquareColor color\n");
  5120.     fprintf(stderr, "\t-debug or -debugMode (True | False)\n");
  5121.     exit(2);
  5122. }
  5123.  
  5124. /*
  5125.  * This is necessary because some C libraries aren't ANSI C compliant yet.
  5126.  */
  5127. char *
  5128. StrStr(string, match)
  5129.     char *string, *match;
  5130. {
  5131.     int i, length;
  5132.  
  5133.     length = strlen(match);
  5134.  
  5135.     for (i = strlen(string) - length; i >= 0; i--, string++)
  5136.         if (!strncmp(match, string, (size_t) length))
  5137.             return string;
  5138.  
  5139.     return NULL;
  5140. }
  5141.  
  5142. int
  5143. StrCaseCmp(s1, s2)
  5144.      char *s1, *s2;
  5145. {
  5146.     char c1, c2;
  5147.  
  5148.     for (;;) {
  5149.         c1 = ToLower(*s1++);
  5150.         c2 = ToLower(*s2++);
  5151.         if (c1 > c2) return 1;
  5152.         if (c1 < c2) return -1;
  5153.         if (c1 == '\000') return 0;
  5154.     }
  5155. }
  5156.  
  5157.  
  5158. int
  5159. ToLower(c)
  5160.      int c;
  5161. {
  5162.     return isupper(c) ? tolower(c) : c;
  5163. }
  5164.  
  5165.  
  5166. int
  5167. ToUpper(c)
  5168.      int c;
  5169. {
  5170.     return islower(c) ? toupper(c) : c;
  5171. }
  5172.  
  5173.  
  5174. #if    SYSTEM_FIVE || SYSV
  5175. #ifdef    IRIX /*??*/
  5176. char *
  5177. PseudoTTY(ptyv)
  5178.     int *ptyv;
  5179.      {
  5180.          char *line;
  5181.  
  5182.          line = (char *)_getpty(ptyv, O_RDWR, 0600, 0);
  5183.          if (0 == line)
  5184.              return NULL;
  5185.          return line;
  5186.      }
  5187. #else    /*!IRIX*/
  5188. char *
  5189. PseudoTTY(ptyv)
  5190.     int *ptyv;
  5191. {
  5192. #if    SVR4
  5193.     char *ptsname(), *ptss;
  5194.  
  5195.     *ptyv = open("/dev/ptmx", O_RDWR);
  5196.     if (*ptyv > 0 ) {
  5197.         if (grantpt(*ptyv) == -1)
  5198.             return NULL;
  5199.         if (unlockpt(*ptyv) == -1)
  5200.             return NULL;
  5201.         if (!(ptss = ptsname(*ptyv)))
  5202.             return NULL;
  5203.         strncpy(ptyname, ptss, sizeof(ptyname));
  5204.         ptyname[sizeof(ptyname) -1] = 0;
  5205.         return ptyname;
  5206.     }
  5207.     
  5208. #else    /* !SVR4 */
  5209.     struct stat stb;
  5210.     int c, i;
  5211.  
  5212.     for (c = 'p'; c <= 'z'; c++)
  5213. #if    defined(HPUX) || defined(hpux)
  5214.         for (i = 0; i < 15 /*??*/; i++) {
  5215.             sprintf(ptyname, "/dev/ptym/pty%c%x", c, i);
  5216. #else /* !HPUX */
  5217.         for (i = 0; i < 16; i++) {
  5218. #ifdef    RTU
  5219.             sprintf(ptyname, "/dev/pty%x", i);
  5220. #else /* !RTU */
  5221.             sprintf(ptyname, "/dev/pty%c%x", c, i);
  5222. #endif /* RTU */
  5223. #endif /* HPUX */
  5224.  
  5225. #ifdef    IRIS
  5226.             *ptyv = open("/dev/ptc", O_RDWR, 0);
  5227.             if (*ptyv < 0)
  5228.                 return NULL;
  5229.             if (fstat(*ptyv, &stb) < 0)
  5230.                 return NULL;
  5231. #else /* !IRIS */
  5232.             if (stat(ptyname, &stb) < 0)
  5233.                 return NULL;
  5234.             *ptyv = open(ptyname, O_RDWR, 0);
  5235. #endif /* IRIS */
  5236.  
  5237.             if (*ptyv >= 0) {
  5238. #if    defined(HPUX) || defined(hpux)
  5239.                 sprintf(ptyname, "/dev/pty/tty%c%x", c, i);
  5240. #else /* !HPUX */
  5241. #ifdef    RTU
  5242.                 sprintf(ptyname, "/dev/ttyp%x", i);
  5243. #else /* !RTU */
  5244. #ifdef    IRIS
  5245.                 sprintf(ptyname, "/dev/ttyq%d",
  5246.                     minor(stb.st_rdev));
  5247. #else /* !IRIS, !RTU, !HPUX */
  5248.                 sprintf(ptyname, "/dev/tty%c%x", c, i);
  5249. #endif /* IRIS */
  5250. #endif /* RTU */
  5251. #endif /* HPUX */
  5252.  
  5253. #ifndef    UNIPLUS
  5254.                 if (access(ptyname, 6) != 0) {
  5255.                     close(*ptyv);
  5256. #ifdef    IRIS
  5257.                     return NULL;
  5258. #else /* !IRIS */
  5259.                     continue;
  5260. #endif /* IRIS */
  5261.                 }
  5262. #endif /* !UNIPLUS */
  5263.  
  5264. #ifdef    IBMRTAIX
  5265.             signal(SIGHUP, SIG_IGN);
  5266. #endif /* IBMRTAIX */
  5267.             return ptyname;
  5268.         }
  5269.     }
  5270.  
  5271. #endif
  5272.     return NULL;
  5273. }
  5274. #endif /*IRIX*/
  5275.  
  5276. #else /* !SYSTEM_FIVE */
  5277.  
  5278. void
  5279. CatchPipeSignal(dummy)
  5280.      int dummy;
  5281. {
  5282.     char message[MSG_SIZ];
  5283.  
  5284.     sprintf(message,
  5285.         "%s chess program (%s) exited unexpectedly",
  5286.         lastMsgFP == toFirstProgFP ? "first" : "second",
  5287.         lastMsgFP == toFirstProgFP ? appData.firstChessProgram
  5288.             : appData.secondChessProgram);
  5289.     fprintf(stderr, "%s: %s\n", programName, message);
  5290.     ShutdownChessPrograms(message);
  5291.     return;
  5292. }
  5293. #endif
  5294.